haskellmonadsliftmonoids

Can not lift multiple parameters in a monad


Hello i am trying to do the following:

module MyMonad where
f::(Monad m),=>m (a->b->c)->m a -> m b -> m c
f mf ma mb=
    ma >>= \a ->
    mb >>= \b ->
    mf >>= \c ->
        return (c a b) 

and use it like this :

f (Just 3) (Just 4) 

And i get the following error:

* Non type-variable argument in the constraint: Num (a -> b -> c)
      (Use FlexibleContexts to permit this)
    * When checking the inferred type
        it :: forall a b c.
              (Num a, Num (a -> b -> c)) =>
              Maybe b -> Maybe c

I didn't know how to put multiple type constraints so i tried like this:

f (Just [3]) (Just [4]) (++) -- (knowing (++) can be applied to any type - being a monoid).

In this case i get the following exception:

* Couldn't match expected type `Maybe b0'
                  with actual type `[a1] -> [a1] -> [a1]'
    * Probable cause: `(++)' is applied to too few arguments
      In the third argument of `f', namely `(++)'
      In the expression: f (Just [3]) (Left [3]) (++)
      In an equation for `it': it = f (Just [3]) (Left [3]) (++)

Solution

  • f requires a monad-wrapped function as the first argument. In your first try, you didn't pass the function at all; in the second, you pass (++) as the last argument.

    The following works fine:

    > f (Just (++)) (Just [3]) (Just [4])
    Just [3,4]
    

    liftM2 (and more generally liftA2) already does something very similar to what you want.

    > import Control.Monad (liftM2)
    > liftM2 (++) (Just [3]) (Just [4])
    Just [3,4]
    > import Control.Applicative (liftA2)
    > liftA2 (++) (Just [3]) (Just [4])
    Just [3,4]