【问题标题】:understanding do notation and bindings理解 do 表示法和绑定
【发布时间】:2015-04-22 17:25:52
【问题描述】:

我对 haskell 非常陌生,我正在尝试了解用于在本文档中创建 Monadic 解析器的方法https://www.cs.nott.ac.uk/~gmh/pearl.pdf

为了正确理解它,我试图做一些不同的事情,而不是完全遵循它,因此,我最终得到了这段代码

newtype Parser a = Parser (String -> Maybe (a, String))

item :: Parser Char
item = Parser (\cs -> case cs of
            "" -> Nothing
            (c:cs) -> Just (c, cs))

getParser (Parser x) = x

instance Monad Parser where
    return x = Parser (\cs -> Just (x,cs))
    (Parser p) >>= f  = Parser (\cs -> let result = p cs in
                  case result of
                    Nothing -> Nothing
                    Just (c,cs') -> getParser (f c) cs')

takeThreeDropSecond :: Parser (Char, Char)
takeThreeDropSecond = do
    c1 <- item
    item
    c2 <- item
    return (c1, c2)

这似乎有效,但我很难理解 do 表示法中发生的事情。

例如;在c1 &lt;- item 中,分配给c1 的是什么?是 Parser 类型中包含的函数,还是该计算的结果,还是其他什么?此外,do 表示法中的第二行只是item,所以它只是运行item 但不分配结果吗?最后,return (c1,c2) 会产生什么?是Parser (String -&gt; Maybe ((c1, c2)), String) 还是只是Just (c1, c2)

【问题讨论】:

    标签: haskell monads do-notation


    【解决方案1】:

    Parser 类型封装了一个函数,该函数可以 1) 使用 Maybe 表示失败,2) 返回未通过 (a, String) 解析的剩余文本以及 3) 已解析的某个值 a,可以是任何东西。 monad 实例是将它们联系在一起的管道。 return 实现围绕一个函数创建了一个 Parser,该函数 1) 以 Just 成功,2) 不修改其输入文本,以及 3) 直接传递给它的值。 &gt;&gt;= 实现采用一个解析器和一个函数,然后返回一个新的解析器,该解析器首先运行 p,然后根据结果是通过还是失败运行 f

    takeThreeDropSecond 中,首先c1 &lt;- item 表示“使用item 解析给定的值,将其结果分配给c1,并将其余输入向前馈送”。这不会将item 解析器中的函数分配给c1,它会将运行item 中的函数的结果分配给当前输入。然后你到达item,它使用item 解析一个值,不将它分配给任何东西,并将其余的输入向前馈送。接下来是c2 &lt;- item,它与第一行基本相同,最后是return (c1, c2),它将扩展为Parser (\cs -&gt; Just ((c1, c2), cs))。这意味着return (c1, c2) 的类型为Parser (Char, Char)。使用类型注释将是

    takeThreeDropSecond :: Parser (Char, Char)
    takeThreeDropSecond = do
        (c1 :: Char) <- (item :: Parser Char)
        (item :: Parser Char)
        (c2 :: Char) <- (item :: Parser Char)
        (return (c1, c2) :: Parser (Char, Char))
    

    请注意,任何单子 do 块的最后一行必须与其所属的函数具有相同的类型。由于return (c1, c2) 的类型为Parser (Char, Char),所以必须takeThreeDropSecond,反之亦然。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-13
      • 2019-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多