haskell - 一元类型混淆

标签 haskell types monads parsec

我正在经历Write Yourself a Scheme in Haskell .这是一个很棒的教程,但我遇到了 parsing exercises 之一:

parseNumber :: Parser LispVal
parseNumber = liftM (Number . read) $ many1 digit

使用以下方法重写 parseNumber:
  • 符号
  • 使用 >>= 运算符的显式排序

  • 我对 do-notation 没有任何问题:
    parseNumber :: Parser LispVal
    parseNumber = do x <- many1 digit 
                     let y = read x
                     return $ Number y
    

    对于#2,我尝试了很多变体,例如:
    parseNumber :: Parser LispVal
    parseNumber = (many1 digit) >>= (liftM (Number . read))
    

    但我一直遇到类型错误。我有两个问题。
  • 为什么我会收到类型错误?我误解了单子(monad)绑定(bind)运算符吗?
  • 为什么我的 do-notation 解决方案没有出现类似的类型错误?

  • 我觉得我缺少关于类型的基本概念?

    最佳答案

    您正在尝试从 do-notation 到 bind notation 的非平凡转换,我建议以“平凡”的方式进行,然后使其无积分。

    记起:

    x <- m === m >>=\x ->
    让 x = e === 让 x = e 在

    然后你有:

    parseNumber = many1 digit >>=\x ->
    让 y = 读入 x
    返回(数字 y)

    (我删除了 $ 以避免出现优先级问题。)

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

    parseNumber = many1 digit >>=\x -> return (Number (read x))
    = many1 digit >>= return .数字 。读

    现在,如果你想使用 liftM ,您需要停止使用绑定(bind),因为提升的函数需要一个单子(monad)值作为其参数。

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

    关于haskell - 一元类型混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5320528/

    相关文章:

    haskell - Haskell中类型的计算是怎样的

    c++ - 将 vector<char> buf(256) 转换为 LPCSTR?

    haskell - 界定 IO 单子(monad)

    haskell - 使用 mapM 保持懒惰

    haskell - 无限循环与IO如何在haskell中工作

    haskell - 有什么方法可以恢复足够的懒惰以在单子(monad)中喜结连理吗?

    scala - 具有多重约束的协方差类型参数

    types - 获得路径归纳以在 Agda 中工作

    haskell - 这个单子(monad) Haskell 函数是否已经存在(或者是已知函数的简单组合)?

    haskell - 有没有办法在 if 语句中使用 IO Bool 而无需绑定(bind)到 haskell 中的名称?