考虑以下错误的解析器编写为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
现在我的问题是,我如何放松这种耦合要求?
您的状态是String,如果你这样做(x : _) <- get,然后x是Char.不能使用read上Char.打印出的错误是由于类型推断反过来起作用:从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),您需要更换read与digitToInt来自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)