Monadic型混乱

dby*_*rne 6 monads haskell types parsec

我正在通过Haskell编写自己的方案.这是一个很棒的教程,但我遇到了一个解析练习:

parseNumber :: Parser LispVal
parseNumber = liftM (Number . read) $ many1 digit
Run Code Online (Sandbox Code Playgroud)

使用以下代码重写parseNumber:

  1. DO-符号
  2. 使用>> =运算符进行显式排序

我没有写带符号的问题:

parseNumber :: Parser LispVal
parseNumber = do x <- many1 digit 
                 let y = read x
                 return $ Number y
Run Code Online (Sandbox Code Playgroud)

对于#2,我尝试了很多变化,例如:

parseNumber :: Parser LispVal
parseNumber = (many1 digit) >>= (liftM (Number . read))
Run Code Online (Sandbox Code Playgroud)

但我一直遇到类型错误.我有两个问题.

  1. 为什么我会遇到类型错误?我是否误解了monadic bind运算符?
  2. 为什么我的口号解决方案没有出现类似的类型错误?

我觉得我错过了关于类型的基本概念?

Edw*_*ang 11

你正在尝试从do-notation到绑定表示法的非平凡转换,我建议以"琐碎"的方式进行,然后使其成为无点.

召回:

 x <- m    === m >>= \x ->
 let x = e === let x = e in

然后你有:

 parseNumber = many1 digit >>= \x ->
               let y = read x in
               return (Number y)

(我删除了$以避免优先级问题.)

然后我们可以将其转换为:

 parseNumber = many1 digit >>= \x -> return (Number (read x))
             = many1 digit >>= return . Number . read

现在,如果要使用liftM,则需要停止使用bind,因为提升的函数需要monadic值作为其参数.

 parseNumber = liftM (Number . read) (many1 digit)