> 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
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe