how to print intermediate result in Functor and Applicative in Haskell

前端 未结 2 820
灰色年华
灰色年华 2021-01-07 03:34

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

相关标签:
2条回答
  • 2021-01-07 04:03

    (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:

    1. Each step should be syntactically valid. No unbound variables, no missing parens, etc.
    2. If the original expression typechecks, then each step must also typecheck and have the same type.
    0 讨论(0)
  • 2021-01-07 04:15

    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:

    1. You could expand the fmap in fmap g item.
    2. You could expand the inner (<*>) in P (...) <*> item.
    3. You could expand the outer (<*>) in (P (...) <*> item) <*> item.

    Good luck!

    0 讨论(0)
提交回复
热议问题