解析器示例不会与我点击(Parser example isn't clicking with me)

编程入门 行业动态 更新时间:2024-10-21 09:46:30
解析器示例不会与我点击(Parser example isn't clicking with me)

我正在通过Real World Haskell进行阅读,并且作为函子/ monads的介绍,它给出了以下示例:

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,弹出一个字节,然后返回一个“修改过的”Parser。 物体来自哪里? 我一直在盯着现在一天,仍然不知道这个功能如何工作。

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

I'm reading through Real World Haskell, and as an intro into functors/monads, it gives the following example:

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

(The rest of it can be read about a quarter of the way down the page at: http://book.realworldhaskell.org/read/code-case-study-parsing-a-binary-data-format.html)

The thing that doesn't make any sense to me is, why does this function not take any parameters? I'd expect it to accept a Parse object containing the text to be parsed, then return the parsed text, and a new Parse object. Instead, (as I see it) it's "magically" accessing a Parser, popping a byte, then returning a "modified" Parser. Where does the object come from? I've been staring at at for a day now and still have no clue how this function works.

Any guidance here would be appreciated.

最满意答案

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地方获取它的输入。

The Parse type is defined as

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

So if you're wondering where the input comes from, it's in the definition of the type! Each Parse value wraps up a function, and then we use ==> in this example to chain two Parses together through composition into a new Parse. This is then finally run using runParse. This function requires a ParseState, being defined as

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

this is what carries the string being parsed.

You can think of the Parse type as an alias for the type

ParseState -> Either String (a, ParseState)

which is a function like you'd expect. With the ==> function having the type (with the newtype wrapper removed)

(==>) :: (ParseState -> Either String (a, ParseState)) -> (a -> (ParseState -> Either String (b, ParseState))) -> (ParseState -> Either String (b, ParseState))

we can then take one Parse and feed it into another Parse to make a new Parse. All of this is no more than a fancy wrapper around regular function composition. It gets it input from where-ever runParse is called from the initial state.

更多推荐

本文发布于:2023-08-05 00:32:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1424569.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:与我   示例   clicking   Parser

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!