使用StateT进行解析的正确方法

Eva*_*ian 1 haskell

考虑以下错误的解析器编写为StateT.

type Parser a = StateT String Maybe a -- Maybe is chosen arbitrarily here.

oneDigit :: Parser Int
oneDigit = do
        (x : _) <- get
        return (read x :: Int)
Run Code Online (Sandbox Code Playgroud)

它抛出以下错误:

No instance for (MonadState [String] (StateT String Maybe))
Run Code Online (Sandbox Code Playgroud)

但是,当我改变时,这并没有发生oneChar :: Parser Char.

我的结论是,你只能定义一个Parser a你的国家m a

现在我的问题是,我如何放松这种耦合要求?

mar*_*iop 6

您的状态是String,如果你这样做(x : _) <- get,然后xChar.不能使用readChar.打印出的错误是由于类型推断反过来起作用:从read x编译器推断出x是a String并且这意味着你的状态是[String],这是不正确的Parser a.具体来说,错误说这(StateT String Maybe)不是一个实例MonadState [String],这是真的,因为它是一个实例MonadState String.你可以从GHCI看到它:

> import Control.Monad.State
> :i StateT
...
instance Monad m => MonadState s (StateT s m)
Run Code Online (Sandbox Code Playgroud)

s == String你的情况.

现在,如果你想读的下一个Char在你的字符串作为一个数字(从0到9的NUM),您需要更换readdigitToInt来自Data.Char:

oneDigit :: Parser Int
oneDigit = do
    (x : _) <- get -- x will be inferred as Char
    return (digitToInt x :: Int)
Run Code Online (Sandbox Code Playgroud)