Refactoring Semigroup/Monoid (was: instance Applicative Data.Map)
Tyson Whitehead
twhitehead at gmail.com
Mon Nov 19 18:25:57 CET 2012
On November 17, 2012 11:18:46 Edward Kmett wrote:
> Honestly, the main issue is that even if you have the ability to describe
> default definitions for how to implement superclasses, it isn't really all
> that useful. :(
I was wondering about the solution demonstrated in the following example of a
re-implementation of the standard Functor, Applicative, Monad hierarchy
class Functor f where
functor_map :: (a -> b) -> f a -> f b
class Applicative f where -- add appropriate defaults for the first bunch
applicative_map :: (a -> b) -> f a -> f b
applicative_pure :: a -> f a
applicative_apply :: f (a -> b) -> f a -> f b
class Monad m where -- add appropriate defaults for the first bunch
monad_map :: (a -> b) -> m a -> m b
monad_pure :: a -> m a
monad_apply :: m (a -> b) -> m a -> m b
monad_join :: m (m a) -> m a
monad_bind :: m a -> (a -> m b) -> m b
with the following functions
fmap :: Functor f => (a -> b) -> f a -> f b
fmap = functor_map
pure :: Applicative f => a -> f a
pure = applicative_pure
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(<*>) = applicative_apply
return :: Monad m => a -> m a
return = monad_pure
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(>>=) = monad_bind
and the following instances
instance Monad m => Applicative m where
applicative_map = monad_map
applicative_pure = monad_pure
applicative_apply = monad_apply
instance Applicative f => Functor f where
functor_map = applicative_map
With this, providing instance at all levels is as easy as
instance Monad [] where
monad_join xss = [x | xs <- xss, x <- xs]
monad_bind xs f = [y | x <- xs, y <- f x]
monad_apply fs xs = [f x | f <- fs, x <- xs]
monad_map f xs = [f x | x <- xs]
monad_pure x = [x]
GHC 7.0.4 accepts this with FlexibleInstances and UndecidableInstances, but it
seems to still have some issues (features?) as it overrides signatures
*Main> :t pure
pure :: Monad f => a -> f a
unless you add other instances that are only at the lowel levels. For
example, adding Maybe at the Applicative level to the above [] instance
instance Applicative Maybe where
applicative_apply (Just f) (Just x) = Just (f x)
applicative_apply _ _ = Nothing
applicative_map f (Just x) = Just (f x)
applicative_map _ _ = Nothing
applicative_pure x = Just x
gives
*Main> :t pure
pure :: Monad f => a -> f a
*Main> :t Main.fmap
Main.fmap :: Applicative f => (a -> b) -> f a -> f b
Cheers! -Tyson
More information about the Libraries
mailing list