{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}

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

-- |

-- Copyright   :  (C) 2021 Koz Ross

-- License     :  BSD-style (see the file LICENSE)

--

-- Maintainer  :  Koz Ross <koz.ross@retro-freedom.nz>

-- Stability   :  Experimental

-- Portability :  GHC only

--

-- Provides a way to attach an identity to any semigroupoid.

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

module Data.Semigroupoid.Categorical (
  Categorical(..),
  runCategorical
  ) where

import Control.Category (Category (id, (.)))
import Data.Semigroupoid (Semigroupoid (o))
import Prelude ()

-- | Attaches an identity.

--

-- @since 5.3.6

data Categorical s a b where
  Id :: Categorical s a a
  Embed :: s a b -> Categorical s a b

-- | @since 5.3.6

instance (Semigroupoid s) => Semigroupoid (Categorical s) where
  Categorical s j k1
Id o :: forall j k1 i.
Categorical s j k1 -> Categorical s i j -> Categorical s i k1
`o` Categorical s i j
y = Categorical s i j
Categorical s i k1
y
  Categorical s j k1
x `o` Categorical s i j
Id = Categorical s j k1
Categorical s i k1
x
  Embed s j k1
x `o` Embed s i j
y = s i k1 -> Categorical s i k1
forall (s :: * -> * -> *) a b. s a b -> Categorical s a b
Embed (s j k1
x s j k1 -> s i j -> s i k1
forall j k1 i. s j k1 -> s i j -> s i k1
forall {k} (c :: k -> k -> *) (j :: k) (k1 :: k) (i :: k).
Semigroupoid c =>
c j k1 -> c i j -> c i k1
`o` s i j
y)

-- | @since 5.3.6

instance (Semigroupoid s) => Category (Categorical s) where
  id :: forall a. Categorical s a a
id = Categorical s a a
forall (s :: * -> * -> *) a. Categorical s a a
Id
  . :: forall b c a.
Categorical s b c -> Categorical s a b -> Categorical s a c
(.) = Categorical s b c -> Categorical s a b -> Categorical s a c
forall b c a.
Categorical s b c -> Categorical s a b -> Categorical s a c
forall {k} (c :: k -> k -> *) (j :: k) (k1 :: k) (i :: k).
Semigroupoid c =>
c j k1 -> c i j -> c i k1
o

-- | @since 5.3.6

runCategorical :: (a ~ b => r) -> (s a b -> r) -> Categorical s a b -> r
runCategorical :: forall a b r (s :: * -> * -> *).
((a ~ b) => r) -> (s a b -> r) -> Categorical s a b -> r
runCategorical (a ~ b) => r
r s a b -> r
_  Categorical s a b
Id = r
(a ~ b) => r
r
runCategorical (a ~ b) => r
_ s a b -> r
f (Embed s a b
x) = s a b -> r
f s a b
x