I am reading the book Programming in Haskell 2nd by Graham Hutton. https://www.cs.nott.ac.uk/~pszgmh/pih.html#slides
When it comes to chapter 13.4 Sequencing parser
It's a good start. Your last step doesn't look quite right. Stripping off the shared parts, you've written that
\inp -> case (\inp -> [(g,inp)]) inp of [] -> []; [(g, out)] -> parse (fmap g item) out
=
parse (fmap g item) out
This equation doesn't look quite right to me: the former is a function, and the latter isn't. Additionally, the latter refers to the free variable out
, while the former doesn't (because out
is bound by the pattern match it's enclosed in). A more careful continuation looks like this:
\inp -> case (\inp -> [(g,inp)]) inp of [] -> []; [(g, out)] -> parse (fmap g item) out
= { beta reduction, substituting inp for inp }
\inp -> case [(g, inp)] of [] -> []; [(g, out)] -> parse (fmap g item) out
= { case reduction, substituting g for g and inp for out }
\inp -> parse (fmap g item) inp
If you like, you could then eta-reduce this to parse (fmap g item)
. Plugging this back into the shared parts we dropped above, we have:
three
=
P (parse (fmap g item)) <*> item <*> item
The result can be verified in ghci:
*Parsing> parse three "abc"
[(('a','c'),"")]
*Parsing> let g x y z = (x,z)
*Parsing> parse (P (parse (fmap g item)) <*> item <*> item) "abc"
[(('a','c'),"")]
As next steps, there are three places you could do your next definition-expansion to enable further progress:
fmap
in fmap g item
.(<*>)
in P (...) <*> item
.(<*>)
in (P (...) <*> item) <*> item
.Good luck!