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
(This is in response to the 'Based on the suggestion of @Daniel Wagner, I expand on fmap g p
:' update)
Is the last substitution correct?
It's impossible to answer because steps before that are incorrect.
There are several problems with your expansion, indicating that you're being sloppy when writing, which has led to mistakes. There might also be conceptual problems.
For example, when you inline three = P ...
into parse three "abc"
, you didn't put parentheses around P ...
, leading to this line:
parse P (parse (P ...)) <*> item <*> item "abc"
This is most likely syntactically incorrect, as it would be parsed like
(parse P (parse (P ...))) <*> item <*> (item "abc")
While you likely meant:
parse ((P ...) <*> item <*> item) "abc"
If you think, well I'm just doing this to make things easier to write, then check this out: This syntax error also led you to erroneously work on the parse P (parse (P ...))
part independently of <*> item <*> item "abc"
, which a serious mistake and made most of everything following that irrelevant.
Another thing is this:
Here, inp="abc", (\inp -> [(g,inp)]), inp = [ (f x y z =(x,z), "abc" )]
This line makes no sense at all. Since you are just expanding three
, It's not valid to say that inp
is anything. Consider (\x -> x)
. The x
here is merely to establish the relationship that the result is the same as the argument, and is not any particular value. This is what is meant by it being a bound variable.
(And I don't even know what you're talking about when you say (\inp -> [(g,inp)]), inp = [ (f x y z =(x,z), "abc" )]
. Maybe you can clarify?)
This also means that the following makes no sense
(\inp -> case parse item inp of [] -> []; [(v, out)] -> [(g v, out)]))<*> item <*> item “abc” ={substitute inp for "abc"} case parse item "abc" of [] -> []; [(v, out)] -> [(g v, out)]<*> item <*> item
There are multiple problems here. To begin with, the first line has an extra close paren, which makes it hard to see what you mean. If we ignore that, then before you had (\inp ->) <*> item ...
, but afterwards you did not put parens around the case
expression, making <*>
.
Also, it seems that you want to do a beta-reduction here. A beta reduction always has the form (\v -> E) a
, in which the lambda is directly applied to an argument. You cannot just say randomly that 'v
is equal to a
' and jump around in expressions.
For example, If we have f (\x -> x + 1) 3
, is it right to reduce that to f 4
? No, because the lambda isn't being applied to 3
.
This means that even if the first half is right, the second half of what you wrote is based on a nonsensical step and is irrelevant.
I would very much want to tell you how to fix your reduction, but I'm sorry to say that I think what you wrote is beyond repair by now. If you want to have a correct reduction trace, please be more careful with both the syntax and the validity of each step, and do everything again from scratch.
As an aid, there are several things you should check to see if things went wrong:
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!