0

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?

Community
  • 1
  • 1
abelard2008
  • 1,984
  • 1
  • 20
  • 35
  • 1
    `runParse` simple retrieves a value from a record. `runParse (Parse (\s -> Right (1,s)))` is exactly equal to `\s -> Right (1,s)`. After that, it is just regular function application. – user2407038 Nov 02 '14 at 04:45
  • @user2407038 thanks! Why these exists such a equation relations? where I can get a relative reference? – abelard2008 Nov 02 '14 at 04:51

1 Answers1

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.

abelard2008
  • 1,984
  • 1
  • 20
  • 35
  • 1
    A few thoughts: `runParse` is defined just as you thought: `runParse (Parse f) = f` so `runParser (Parse p) a = p a` which means in you example the entire thing ends in `Right (1, ... the state ...)` which is indeed what we see – daniel gratzer Nov 02 '14 at 14:50