monoids-in-the-category-of-.../src/Functor/Base.hs

87 lines
2.5 KiB
Haskell

module Functor.Base where
import Relation
import Data.Functor.Const (Const (Const), getConst)
import Data.Functor.Identity (Identity (Identity), runIdentity)
import Data.Either (Either (Left, Right))
import Data.Kind (Constraint, Type)
import Data.Maybe (Maybe (Just, Nothing))
type Functor :: (j -> k) -> Constraint
class (Category (Cod f), Category (Dom f)) => Functor (f :: j -> k) where
type Cod f :: Relation k
type Dom f :: Relation j
map :: Dom f x y -> Cod f (f x) (f y)
type Endofunctor :: (k -> k) -> Constraint
type Endofunctor f = (Functor f, Cod f ~ Dom f)
-- This can't be placed in a separate Category.Functor file
-- because the Functor instances for built-in types require Nat.
-- | A natural transformation between functors.
type Nat :: (k -> k -> Type) -> (j -> j -> Type) -> (j -> k) -> (j -> k) -> Type
data Nat dest src f g = (Functor f, Functor g, Dom f ~ src, Dom g ~ src, Cod f ~ dest, Cod g ~ dest) => Nat { runNat :: !(forall a. Object src a -> dest (f a) (g a)) }
instance Reflexive (Nat dest src) where
idL (Nat _) = Nat map
idR (Nat _) = Nat map
instance Transitive (Nat dest src) where
Nat f . Nat g = Nat \x -> f x . g x
instance Functor Maybe where
type Cod Maybe = (->)
type Dom Maybe = (->)
map f = \case
Just x -> Just (f x)
Nothing -> Nothing
instance Functor (Either a) where
type Cod (Either a) = (->)
type Dom (Either a) = (->)
map f = \case
Left y -> Left y
Right x -> Right (f x)
instance Functor ((,) a) where
type Cod ((,) a) = (->)
type Dom ((,) a) = (->)
map f = \(x, y) -> (x, f y)
instance Functor ((->) a) where
type Cod ((->) a) = (->)
type Dom ((->) a) = (->)
map = (.)
instance Functor Either where
type Cod Either = Nat (->) (->)
type Dom Either = (->)
map g = Nat \_ -> \case
Left y -> Left (g y)
Right x -> Right x
instance Functor (,) where
type Cod (,) = Nat (->) (->)
type Dom (,) = (->)
map g = Nat \_ (y, x) -> (g y, x)
instance Functor (->) where
type Cod (->) = Nat (->) (->)
type Dom (->) = Opposite (->)
map (Opposite f) = Nat \_ g -> (g . f)
instance Functor Identity where
type Cod Identity = (->)
type Dom Identity = (->)
map f = Identity . f . runIdentity
instance Functor (Const a :: Type -> Type) where
type Cod (Const a) = (->)
type Dom (Const a) = (->)
map _ = Const . getConst
instance Functor (Const :: Type -> Type -> Type) where
type Cod Const = Nat (->) (->)
type Dom Const = (->)
map f = Nat \_ -> Const . f . getConst