Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Monadic equivalent of applicative <*

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?

like image 822
gawi Avatar asked Dec 27 '22 12:12

gawi


1 Answers

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.)

like image 192
Heinrich Apfelmus Avatar answered Jan 05 '23 11:01

Heinrich Apfelmus