views:

168

answers:

3

When working with monadic expressions in Haskell, the use of liftM's (even in infix position) often seems quite unaesthetic and verbose to me.

Most other monadic primitives (>>=, >>) and even liftM's pure pendant $ are infix operators. This makes me think why there is no operator symbol for monadic lifting.

Do you have reasonable, consistent suggestions for an operator symbol (or why there shouldn't be one)? (I thought of >- and -< (shifting the monad through a function), but they seem to have different meanings in the context of arrows.)

+6  A: 

You can use the <$> operator from Control.Applicative.

EDIT: Unfortunately <$> only works for some Monads which are instances of Applicative. Defining some instance Monad m => Applicative m is not possible as this would overlap with the existing Applicative instances IO, Maybe and [].

Long
All monads are applicative. Creating an instance of Applicative for a monad is as simple as declaring `a <$> f = a >>= (return . f)` and `(<*>) = ap`.
Apocalisp
By the way, `(liftM2 f) x y` is equivalent to `f <$> x <*> y`. Ditto for `liftM3`, etc. Just keep adding `<*>`.
Apocalisp
`"Defining some instance Monad m => Applicative m is not possible as this would overlap with the existing Applicative instances IO, Maybe and []."` Maybe I'm not getting it, but even if you could, you wouldn't need to because you already have `<$>` at your disposal for these types.
trinithis
+3  A: 

I'd consider something like <$ (<<$ for liftM2, <<<$ for liftM3).

Alexey Romanov
+1 for making it look right for liftM2 and liftM3
barkmadley
+1  A: 

Since liftM == fmap and (.) == fmap for functions (the ((->) r) instance of Functor), I suggest hiding (.) from Prelude and defining:

import Prelude hiding ((.))
import Control.Monad.Instances () -- import Functor instance for functions

infixr 9 .    
(.) :: (Functor f) => (a -> b) -> (f a -> f b)
(.) = fmap

Examples:

foo = (\x -> x ^ 2) . (\x -> x + 1)
(+1) . [1, 2, 3]
someIO =<< read . getLine -- more useful in do notation because of following
someIO . read =<< getLine -- equivalent to above but uses different instance
trinithis