packages feed

kindly-functors-0.1.0.0: src/Kindly/Trifunctor.hs

{-# LANGUAGE ImpredicativeTypes #-}
{-# OPTIONS_GHC -Wno-orphans #-}

-- | Three Parameter Functors of arbitrary varience.
module Kindly.Trifunctor
  ( Trifunctor,
    trimap,
  )
where

--------------------------------------------------------------------------------

import Control.Category
import Data.Kind (Constraint, Type)
import Kindly.Bifunctor ()
import Kindly.Class

--------------------------------------------------------------------------------

-- | A 'CategoricalFunctor' of kind @Type -> Type -> Type@ mapping from an
-- arbitrary category @cat1@ to a functor category @cat2 ~> cat3 ~> (->)@.
type Trifunctor :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> (Type -> Type -> Type) -> (Type -> Type -> Type -> Type) -> Constraint
type Trifunctor cat1 cat2 cat3 p = (MapArg3 cat3 cat2 cat1 p, forall x. MapArg2 cat2 cat1 (p x), forall x y. MapArg1 cat1 (p x y))

-- | Lift a morphism @cat1 a a'@, a morphism @cat2 b b'@, and a morphism @cat3 c c'@ into a -- function @p a b c -> p a' b' c'@.
trimap :: forall cat1 cat2 cat3 p. (Trifunctor cat1 cat2 cat3 p) => forall a b c a' b' c'. (a `cat3` a') -> (b `cat2` b') -> (c `cat1` c') -> p a b c -> p a' b' c'
trimap f g h = map3 f . map2 @_ @cat1 g . map1 h

--------------------------------------------------------------------------------

instance CategoricalFunctor (,,) where
  type Dom (,,) = (->)
  type Cod (,,) = (->) ~> (->) ~> (->)

  map :: (a -> b) -> ((->) ~> (->) ~> (->)) ((,,) a) ((,,) b)
  map f = Nat (Nat (\(x, y, z) -> (f x, y, z)))

instance CategoricalFunctor ((,,,) x) where
  type Dom ((,,,) x) = (->)
  type Cod ((,,,) x) = (->) ~> (->) ~> (->)

  map :: (a -> b) -> ((->) ~> (->) ~> (->)) ((,,,) x a) ((,,,) x b)
  map f = Nat (Nat (\(a, b, c, d) -> (a, f b, c, d)))

instance CategoricalFunctor ((,,,,) x x') where
  type Dom ((,,,,) x x') = (->)
  type Cod ((,,,,) x x') = (->) ~> (->) ~> (->)

  map :: (a -> b) -> ((->) ~> (->) ~> (->)) ((,,,,) x x' a) ((,,,,) x x' b)
  map f = Nat (Nat (\(a, b, c, d, e) -> (a, b, f c, d, e)))

instance CategoricalFunctor ((,,,,,) x x' x'') where
  type Dom ((,,,,,) x x' x'') = (->)
  type Cod ((,,,,,) x x' x'') = (->) ~> (->) ~> (->)

  map :: (a -> b) -> ((->) ~> (->) ~> (->)) ((,,,,,) x x' x'' a) ((,,,,,) x x' x'' b)
  map f' = Nat (Nat (\(a, b, c, d, e, f) -> (a, b, c, f' d, e, f)))

instance CategoricalFunctor ((,,,,,,) x x' x'' x''') where
  type Dom ((,,,,,,) x x' x'' x''') = (->)
  type Cod ((,,,,,,) x x' x'' x''') = (->) ~> (->) ~> (->)

  map :: (a -> b) -> ((->) ~> (->) ~> (->)) ((,,,,,,) x x' x'' x''' a) ((,,,,,,) x x' x'' x''' b)
  map f' = Nat (Nat (\(a, b, c, d, e, f, g) -> (a, b, c, d, f' e, f, g)))

--------------------------------------------------------------------------------

instance MapArg3 (->) (->) (->) (,,)

instance MapArg3 (->) (->) (->) ((,,,) x)

instance MapArg3 (->) (->) (->) ((,,,,) x x')

instance MapArg3 (->) (->) (->) ((,,,,,) x x' x'')

instance MapArg3 (->) (->) (->) ((,,,,,,) x x' x'' x''')