> This, to me, is a big hint that applicative functors could be useful.   

Indeed, the ideas here also apply to applicative functors; it is just the 
lifting primitives that will be different; instead of having liftM<N>, we can 
use <$> and <*> to lift the functions. We could have done this for Num and 
Maybe (suppose Maybe is an instance of Applicative):

instance (Num a) => Num (Maybe a) where
        (+) = \x y -> (+) <$> x <*> y
        (-) = \x y -> (-) <$> x <*> y
        (*) = \x y -> (+) <$> x <*> y
        abs = abs <$>
        signum = signum <$>
        fromInteger = pure . fromInteger

The larger goal remains the same: autolifting in a principled manner.

However, you actually bring up a very good point; what if it is really only the 
applicative functors that this method works on in general, that there is no 
'use case' for considering this autolifting for monads in particular?
I think the answer lies in the fact that monads can be 'flattened;' that is, 
realizations of the type m (m a) -> m a are mechanical (in the form of 'join') 
given that >>= is defined. This is important when we have a typeclass that also 
has monadic signatures. To be more concrete, consider how this function could 
be used in a 'monadic DSL':

enter x = case x of
        0 -> Nothing
        _ -> Just "hi"

The type of 'enter' is one case of the general from 'a -> M b'. If we were 
instancing a typeclass that had an 'a -> M b' function, we'd need a function of 
type 'M a -> M b'. This would be accomplished by 

enter' = join . liftM enter

So the set of lifting primitives must include at least some way to get M a -> M 
b from 'a -> M b'---which requires that M is a monad, not just an applicative 
functor.

Thanks for the mention of applicative functors; I should have included them in 
the original post.

Lingfeng Yang
lyang at cs dot stanford dot edu

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to