After having read Anthony's response on a style-related parser question, I was trying to convince myself that writing monadic parsers can still be rather compact.
So instead of
reference :: Parser Transc
reference = try $ do string "#{"
a <- number
char ','
b <- number
char ','
c <- number
char '}'
return $ Outside (a,b,c)
We can simply have:
reference3 :: Parser Transc
reference3 = liftM3 (((Outside .).) . (,,))
(string "#{" >> number <<! char ',')
number
(char ',' >> number <<! char '}') where
(<<!) = liftM2 const
Which is very similar to applicative version provided by Anthony:
reference2 :: Parser Transc
reference2 = ((Outside .) .) . (,,)
<$> (string "#{" *> number2 <* char ',')
<*> number2
<*> (char ',' *> number2 <* char '}')
...except for the <<!
operator which is conceptually similar to <*
which is defined as liftA2 const
meaning "sequence but discard value and use value provided to the left".
Of course << would have been a bad name for liftM2 const
, it would have suggested that <<
is equivalent to flip >>
if we follow the same logic as >>=
and =<<
.
I don't find a "liftM2 const" under a single name. Is this because it is not that useful?
I don't quite see the problem. Every monad is also an of applicative functor, so you can simply use (*>)
in the monadic expressions as well.
(At the time of this answer (year 2011), Applicative
was not a superclass of Monad
, so it may have been necessary to add a corresponding class instance.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With