-----------------------------------------------------------------------------
-- |
-- Module : Control.Functor
-- Copyright : 2004 Dave Menendez
-- License : public domain
--
-- Maintainer : dan.doel@gmail.com
-- Stability : experimental
-- Portability : portable
--
-- Functor composition, standard functors, and more.
--
-----------------------------------------------------------------------------
module Control.Functor
(
-- * Unary functors
-- ** Composition
O(..)
, lComp
, rComp
-- ** Basic Instances
-- *** Unit
, Unit(..)
-- *** Const
, Const(..)
-- * Binary functors
, Bifunctor(..)
-- * Trinary functors
, Trifunctor(..)
) where
infixr 2 `O`
{-|
Functor composition.
(Note: Some compilers will let you write @f \`O\` g@ rather than @O f g@;
we'll be doing so here for readability.)
Functor composition is associative, so @f \`O\` (g \`O\` h)@ and @(f \`O\` g) \`O\` h@
are equivalent. The functions 'lComp' and 'rComp' convert between the two.
(Operationally, they are equivalent to @id@. Their only purpose is to affect
the type system.)
-}
newtype (O f g) a = Comp { deComp :: f (g a) }
instance (Functor f, Functor g) => Functor (O f g) where
fmap f = Comp . fmap (fmap f) . deComp
lComp :: (Functor f) => (O f (O g h)) a -> (O (O f g) h) a
lComp = Comp . Comp . fmap deComp . deComp
rComp :: (Functor f) => (O (O f g) h) a -> (O f (O g h)) a
rComp = Comp . fmap Comp . deComp . deComp
{-|
The unit functor.
(Note: this is not the same as @()@. In fact, 'Unit' is the
fixpoint of @()@.)
-}
data Unit a = Unit deriving (Show)
instance Functor Unit where
fmap _ _ = Unit
instance Monad Unit where
return _ = Unit
_ >>= _ = Unit
{-|
Constant functors. Essentially the same as 'Unit', except that they also
carry a value.
-}
data Const t a = Const { unConst :: t } deriving (Show)
instance Functor (Const t) where
fmap _ (Const t) = Const t
{-|
A type constructor which takes two arguments and an associated map function.
Informally, @Bifunctor f@ implies @Functor (f a)@ with @fmap = bimap id@.
-}
class Bifunctor f where
bimap :: (a -> c) -> (b -> d) -> (f a b -> f c d)
instance Bifunctor (,) where
bimap f g (x,y) = (f x, g y)
instance Bifunctor Either where
bimap f _ (Left x) = Left (f x)
bimap _ g (Right x) = Right (g x)
{-
instance (Trifunctor f) => Bifunctor (f a) where
bimap = trimap id
-}
{-|
A type constructor which takes three arguments and an associated map function.
Informally, @Trifunctor f@ implies @Bifunctor (f a)@ with @bimap = trimap id@.
-}
class Trifunctor f where
trimap :: (a -> a') -> (b -> b') -> (c -> c') -> (f a b c -> f a' b' c')
instance Trifunctor (,,) where
trimap f g h (x,y,z) = (f x, g y, h z)