解析器示例不是与我点击

时间:2014-09-05 19:51:58

标签: haskell monads

我通过Real World Haskell阅读,作为仿函数/ monad的介绍,它给出了以下示例:

parseByte :: Parse Word8
parseByte =
    getState ==> \initState ->
    case L.uncons (string initState) of
      Nothing ->
          bail "no more input"
      Just (byte,remainder) ->
          putState newState ==> \_ ->
          identity byte
        where newState = initState { string = remainder,
                                     offset = newOffset }
              newOffset = offset initState + 1

(其余部分可以在页面的四分之一处阅读:http://book.realworldhaskell.org/read/code-case-study-parsing-a-binary-data-format.html

对我来说没有任何意义的是,为什么这个功能不带任何参数?我希望它接受包含要解析的文本的Parse对象,然后返回解析的文本和新的Parse对象。相反,(我认为),它是神奇的"访问Parser,弹出一个字节,然后返回一个" modified"分析器。对象来自哪里?我现在一直盯着看了一天,仍然不知道这个功能是如何工作的。

这里的任何指导都将不胜感激。

1 个答案:

答案 0 :(得分:6)

Parse类型定义为

newtype Parse a = Parse
    { runParse :: ParseState -> Either String (a, ParseState)
    }

因此,如果您想知道输入的来源,那就是类型的定义!每个Parse值都会包含一个函数,然后我们在此示例中使用==>将两个Parse组合在一起,通过组合成一个新的Parse。然后最终使用runParse运行。此函数需要ParseState,定义为

data ParseState = ParseState
    { string :: L.ByteString
    , offset :: Int64
    } deriving (Show)

这是带解析字符串的内容。

您可以将Parse类型视为类型

的别名
ParseState -> Either String (a, ParseState)

这是一个你期望的功能。使用==>函数具有类型(删除了newtype包装器)

(==>)
    ::       (ParseState -> Either String (a, ParseState))
    -> (a -> (ParseState -> Either String (b, ParseState)))
    ->       (ParseState -> Either String (b, ParseState))
然后,我们可以将Parse一个Parse并将其反馈到另一个Parse以制作新的runParse。所有这些只不过是常规功能组合的花哨包装。它从初始状态调用从{{1}}开始的输入。