Haskell 一元型混淆
我正在经历。这是一个很棒的教程,但我遇到了一个: 使用以下命令重写parseNumber:Haskell 一元型混淆,haskell,types,monads,parsec,Haskell,Types,Monads,Parsec,我正在经历。这是一个很棒的教程,但我遇到了一个: 使用以下命令重写parseNumber: 做记号 使用>>=运算符进行显式排序 我对do符号没有任何问题: parseNumber :: Parser LispVal parseNumber = do x <- many1 digit let y = read x return $ Number y 但我总是遇到类型错误。我有两个问题 为什么我会出现类型错误?我是不是误
parseNumber :: Parser LispVal
parseNumber = do x <- many1 digit
let y = read x
return $ Number y
但我总是遇到类型错误。我有两个问题
我觉得我缺少了一个关于类型的基本概念?如果您正在尝试从do表示法到bind表示法的非平凡转换,我建议您以“平凡”的方式进行转换,然后使其自由指向 回顾: x <- m === m >>= \x -> let x = e === let x = e in 现在,如果您想使用
liftM
,您需要停止使用bind,因为提升函数需要一个一元值作为其参数
parseNumber = liftM (Number . read) (many1 digit)
parseNumber=liftM(Number.read)(多个1位)
在您的情况下,bind具有以下类型:
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
(因为您使用的是解析器
作为Monad)
您给bind两个参数:第一个参数,many1位
,应该是ok(关于类型);但是第二个参数的类型是liftM
的结果类型,即Parser a->Parser b
,这不符合第二个参数的预期类型(a->Parser b)
在没有测试它的情况下:不要使用
liftM(Number.read)
作为bind的第二个参数,而是尝试使用return。号码。阅读
-这应该是正确的类型,可能会给出您想要的…非常好的答案。现在它变得更有意义了。
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
parseNumber = liftM (Number . read) (many1 digit)
(>>=) :: Parser a -> (a -> Parser b) -> Parser b