如何在这里正确使用 StateT monad?

How to properly use the StateT monad here?

我必须在 Haskell 中为我学习的课程制作一个非常小的游戏。所以我创建了播放功能,但现在我无法更改它的类型签名。

play :: [[String]] -> StateT GameState IO Score
play input = 
do 
    liftIO $ clearScreen
    (answered, correct) <- get
    if True
    then
        do
            liftIO $ putStrLn "Well done! Your answer was correct!"
            liftIO $ putStrLn ("So far, you answered " ++ (show answered) ++ " questions")
            put (answered + 1, correct + 1)
            liftIO $
                do
                    temp <- getLine
                    putStrLn temp
    else
        do
            liftIO $ putStrLn "I'm sorry, you're wrong..."
            put (answered + 1, correct)
    play input

现在,请不要介意 if True 语句,那只是为了测试。现在这个函数可以工作了,但我必须让它与另一个类型签名一起工作。函数 play 的类型签名应该是:

play :: IO (Either ParseError [[String]]) -> StateT GameState IO Score

但是我完全不知道如何使用我的 StateT monad?我怎样才能做到这一点? IO (Either ParseError [[String]]) monad 是来自缺失的 H 包的 parseFromFile 函数的结果。

来电者应该处理那个。

main :: IO ()
main = do
  parsed <- parseFromFileStuff
  case parsed of
    Left parseerror -> handleErrorStuff
    Right input -> evalStateT (play input) initialState

顺便说一下,你从来没有真正 return 得分,所以 play 的 return 类型应该是 Void,而不是 Score。此外,您应该通过删除 play 的最后一行、将其 return 类型更改为 () 并将 play input 替换为 forever (play input) 来收紧该递归。哦,你从不使用输入。