Monads and Maybe
Ross Paterson
ross@soi.city.ac.uk
Sat, 23 Aug 2003 13:32:43 +0100
On Thu, Aug 21, 2003 at 11:32:47AM +0100, C T McBride wrote:
> My point, however, is not to use <$> with that type, but the more general
>
> class Fun f where
> eta :: x -> f x
> (<$>) :: f (s -> t) -> f s -> f t
>
> Is there a better name for Fun? Is it ancient and venerable? Am I an
> ignoramus twice over?
It seems that something this useful should have a name, but I've been
unable to find one. This interface was first used for parsers by
Niklas Rojemo. Doaitse Swierstra has developed a lot of interesting
parsers with this interface, roughly
infixl 4 <$>, <*>
class Functor f => Sequence f where
eta :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(<$>) :: (a -> b) -> f a -> f b
(<$>) = fmap
One would expect this to satisfy identity and associativity laws:
eta f <*> v = f <$> v
u <*> eta y = ($ y) <$> u
u <*> (v <*> w) = ((.) <$> u <*> v) <*> w
as well as naturality of eta and (<*>).
Several other choices of primitives are available. One is:
lift0 :: a -> f a
lift1 :: (a -> b) -> f a -> f b
lift2 :: (a -> b -> c) -> f a -> f b -> f c
lift0 = eta
lift1 = fmap
lift2 f fa fb = f <$> fa <*> fb
(<*>) = lift2 ($)
Another interface is eta plus
mult :: f a -> f b -> f (a,b)
with axioms
eta x `mult` v = fmap (\y -> (x,y)) v
u `mult` eta y = fmap (\x -> (x,y)) u
u `mult` (v `mult` w) = fmap assoc ((u `mult` v) `mult` w)
where assoc ((x,y),z) = (x,(y,z))
These are all equivalent (or would be, if Haskell had true products).
The last version generalizes to any symmetric monoidal category: it
requires that f be a lax monoidal functor, with eta_1 and mult as the
transformations, that eta is a transformation from the identity monoidal
functor to f, plus the symmetry condition
eta x `mult` v = fmap swap (v `mult` eta x)
As you note, they're preserved under composition. They also compose
with arrows (in the sense of Hughes) to make new arrows, and they're
preserved by products (as are arrows).