How does the function embeded in runParse of RWH get parameter with type ParseState?

半腔热情 提交于 2019-12-25 06:57:38

问题


After reading LYAH's Chapter 08 and SO questions (1, 2) about Real World Haskell's Parse definition:

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

For me, now I think it is a key understanding how runParse is evaluated when runParse is viewed as a function.

(1) ghci> :t runParse will get

runParse :: Parse a -> ParseState -> Either String (a, ParseState)

(2) For trying runParse, similar to RWH's The identity Parser , I used the following example:

ghci> runParse (Parse (\s -> Right (1,s))) (ParseState (L8.pack "") 0)

I got the result:

Right (1,ParseState {string = "", offset = 0})

I can guess that the above evaluation is that (Parse (\s -> Right (1,s))) and (ParseState (L8.pack "") 0) first are parameters of runParse and anonymous function (\s -> Right (1, s)) uses (ParseState (L8.pack "") 0) as its parameter . But this guess makes me confused:

Why (ParseState (L8.pack "") 0) is used as (\s -> Right (1, s)) 's parameter during evaluating? How does the whole runParse eval finish?

Also, I can write an alternative function for a simple definition, such as in LYAH:

newtype CharList = CharList {getCharList :: [Char]}

For this, CharList and getCharList can be defined as:

newtype CharList = CharList [Char]

getCharList :: CharList -> [Char]
getCharList cl = case cl of
    CharList x -> x

So, in the first definition for CharList, it is sure that there exists a pattern match. If I can implement a explicit function with pattern match like this for the previous runParse I will understand it. But I don't know how to do it?


回答1:


After several hours, I think I can answer this myself.

Because runParse is a function with two parameters:

runParse :: Parse a -> ParseState -> Either String (a, ParseState)

After reviewing Partial Function Application principal RWH descriped : In Haskell, all functions take only one argument. I know that

ghci> runParse (Parse (\s -> Right (1,s))) (ParseState (L8.pack "") 0) 

and :

ghci> let y = runParse (Parse (\s -> Right (1,s)))
ghci> y (ParseState (L8.pack "") 0)

are the same, and in ghci this evaluation must be divided into two steps:

(1) evaluating the function runParse with a parameter Parse a, which returns a function with a parameter with type ParseState, if Parse a is (Parse (\s -> Right (1,s))) , according to the simplest example in LYAH:

ghci> newtype CharList = CharList {getCharList :: [Char]}
ghci> getCharList (CharList "ab")
"ab"

so the result of executing

runParse (Parse (\s -> Right (1,s))) is (\s -> Right (1,s)), and it is verified from the fact: the type of ghci> :t runParse (Parse (\s -> Right (1,s))) is

runParse (Parse (\s -> Right (1,s))) :: Num a => ParseState -> Either String (a, ParseState)

(2) after difficult step (1) for me, I get a function called y in this case, which needs a parameter with a type ParseState, y (ParseState (L8.pack "") 0) will get a predicated result: Right (1,ParseState {string = "", offset = 0})

I need keep it in mind that , for a function with more than one parameters, either you give all parameters one time or you give one parameter one time, the function's evaluation flow always includes the same amount as the number of parameters of steps and every step evaluates a function with one parameter.



来源:https://stackoverflow.com/questions/26696064/how-does-the-function-embeded-in-runparse-of-rwh-get-parameter-with-type-parsest

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!