{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE PolyKinds #-}
{-# OPTIONS_GHC -Wno-inline-rule-shadowing #-}
    -- The RULES for the methods of class Category may never fire
    -- e.g. identity/left, identity/right, association;  see Trac #10528

-----------------------------------------------------------------------------
-- |
-- Module      :  Control.Category
-- Copyright   :  (c) Ashley Yakeley 2007
-- License     :  BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer  :  ashley@semantic.org
-- Stability   :  experimental
-- Portability :  portable

-- http://ghc.haskell.org/trac/ghc/ticket/1773

module Control.Category where

import qualified GHC.Base (id,(.))
import Data.Type.Coercion
import Data.Type.Equality
import GHC.Prim (coerce)

infixr 9 .
infixr 1 >>>, <<<

-- | A class for categories. Instances should satisfy the laws
--
-- [Right identity] @f '.' 'id'  =  f@
-- [Left identity]  @'id' '.' f  =  f@
-- [Associativity]  @f '.' (g '.' h)  =  (f '.' g) '.' h@
--
class Category cat where
    -- | the identity morphism
    id :: cat a a

    -- | morphism composition
    (.) :: cat b c -> cat a b -> cat a c

{-# RULES
"identity/left" forall p .
                id . p = p
"identity/right"        forall p .
                p . id = p
"association"   forall p q r .
                (p . q) . r = p . (q . r)
 #-}

-- | @since 3.0
instance Category (->) where
    id :: a -> a
id = a -> a
forall a. a -> a
GHC.Base.id
    . :: (b -> c) -> (a -> b) -> a -> c
(.) = (b -> c) -> (a -> b) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
(GHC.Base..)

-- | @since 4.7.0.0
instance Category (:~:) where
  id :: a :~: a
id          = a :~: a
forall k (a :: k). a :~: a
Refl
  Refl . :: (b :~: c) -> (a :~: b) -> a :~: c
. Refl = a :~: c
forall k (a :: k). a :~: a
Refl

-- | @since 4.10.0.0
instance Category (:~~:) where
  id :: a :~~: a
id            = a :~~: a
forall k (a :: k). a :~~: a
HRefl
  HRefl . :: (b :~~: c) -> (a :~~: b) -> a :~~: c
. HRefl = a :~~: c
forall k (a :: k). a :~~: a
HRefl

-- | @since 4.7.0.0
instance Category Coercion where
  id :: Coercion a a
id = Coercion a a
forall k (a :: k) (b :: k). Coercible a b => Coercion a b
Coercion
  . :: Coercion b c -> Coercion a b -> Coercion a c
(.) Coercion = Coercion a b -> Coercion a c
forall a b. Coercible a b => a -> b
coerce

-- | Right-to-left composition
(<<<) :: Category cat => cat b c -> cat a b -> cat a c
<<< :: cat b c -> cat a b -> cat a c
(<<<) = cat b c -> cat a b -> cat a c
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
(.)

-- | Left-to-right composition
(>>>) :: Category cat => cat a b -> cat b c -> cat a c
f :: cat a b
f >>> :: cat a b -> cat b c -> cat a c
>>> g :: cat b c
g = cat b c
g cat b c -> cat a b -> cat a c
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. cat a b
f