Search code examples
parsinghaskellfunctional-programmingmonads

What does <* in Haskell readP do?


I have encountered <* in the Haskell readP library on several occassions, I am however not yet sure what it does, and couldn't find it in the library documentation. Is it the same as <++ ?


Solution

  • (<*) :: Applicative f => f a -> f b -> f a is not specific to ReadP, it is part or Applicative, and essentially boils down to:

    f <* g = do
      y <- f
      g
      pure y
    

    but this is, unless using an ApplicativeDo for monads. But it makes it quite clear what is happening.

    Behind the curtains it is implemented as:

    f <* g = liftA2 const f g
    

    so it "merges" two Applicative f => f as, and by using const, it will take the first item, not the second.

    it thus uses the left operand, then the right, and return the result of the first one.

    In the context of the ReadP, it thus will run the left parser, then the right, and then omit the result of the right parser and return the first parser.

    For example:

    get <* get
    

    it will read two characters, and return the first parsed character, so ignoring (but parsing) the right character.

    The (<++) :: ReadP a -> ReadP a -> ReadP is about choices where you present two choices as parser, and you first try to run the left parser, and if that fails the second parser. But here if for example the first parser matches, it will never run the second parser for the rest of the stream.