packages feed

pandora-0.5.0: Pandora/Paradigm/Schemes/TT.hs

{-# LANGUAGE UndecidableInstances #-}
module Pandora.Paradigm.Schemes.TT where

import Pandora.Core.Functor (type (:.), type (:=), type (~>))
import Pandora.Pattern.Betwixt (Betwixt)
import Pandora.Pattern.Semigroupoid (Semigroupoid ((.)))
import Pandora.Pattern.Category (identity)
import Pandora.Pattern.Functor.Covariant (Covariant ((<-|-)), (<-|-|-))
import Pandora.Pattern.Functor.Contravariant (Contravariant)
import Pandora.Pattern.Functor.Semimonoidal (Semimonoidal (mult))
import Pandora.Pattern.Functor.Monoidal (Monoidal (unit))
import Pandora.Pattern.Functor.Traversable (Traversable ((<<-)), (<<-<<-))
import Pandora.Pattern.Functor.Distributive (Distributive ((-<<)))
import Pandora.Pattern.Functor.Bindable (Bindable ((=<<)))
import Pandora.Pattern.Transformer.Liftable (Liftable (lift))
import Pandora.Pattern.Transformer.Lowerable (Lowerable (lower))
import Pandora.Pattern.Transformer.Hoistable (Hoistable ((/|\)))
import Pandora.Paradigm.Controlflow.Effect.Interpreted (Interpreted (Primary, run, unite, (!), (||=)))
import Pandora.Paradigm.Primary.Algebraic.Exponential (type (<--), type (-->))
import Pandora.Paradigm.Primary.Algebraic.Product ((:*:) ((:*:)))
import Pandora.Paradigm.Primary.Algebraic.Sum ((:+:), bitraverse_sum)
import Pandora.Paradigm.Primary.Algebraic.One (One (One))
import Pandora.Paradigm.Primary.Algebraic (empty, point, extract, (<-|-<-|-))
import Pandora.Pattern.Morphism.Flip (Flip (Flip))
import Pandora.Pattern.Morphism.Straight (Straight (Straight))

newtype TT ct ct' t t' a = TT (t :. t' := a)

infixr 3 <::>, >::>, <::<, >::<

type (<::>) = TT Covariant Covariant
type (>::>) = TT Contravariant Covariant
type (<::<) = TT Covariant Contravariant
type (>::<) = TT Contravariant Contravariant

instance Interpreted (->) (TT ct ct' t t') where
	type Primary (TT ct ct' t t') a = t :. t' := a
	run ~(TT x) = x
	unite = TT

instance (Semigroupoid m, Covariant m m t, Covariant (Betwixt m m) m t, Covariant m (Betwixt m m) t', Interpreted m (t <::> t')) => Covariant m m (t <::> t') where
	(<-|-) f = (||=) ((<-|-|-) f)

instance (Covariant (->) (->) t, Semimonoidal (-->) (:*:) (:*:) t, Semimonoidal (-->) (:*:) (:*:) t') => Semimonoidal (-->) (:*:) (:*:) (t <::> t') where
	mult = Straight ! TT . (<-|-) (mult @(-->) !) . (mult @(-->) !) . (run :*: run <-|-<-|-)

instance (Covariant (->) (->) t, Covariant (->) (->) t', Semimonoidal (-->) (:*:) (:*:) t', Monoidal (-->) (-->) (:*:) (:*:) t, Monoidal (-->) (-->) (:*:) (:*:) t') => Monoidal (-->) (-->) (:*:) (:*:) (t <::> t') where
	unit _ = Straight ! TT . point . point . (! One) . run

instance (Covariant (->) (->) t, Covariant (->) (->) t', Semimonoidal (-->) (:*:) (:+:) t) => Semimonoidal (-->) (:*:) (:+:) (t <::> t') where
	mult = Straight ! \(TT x :*: TT y) -> TT ! bitraverse_sum identity identity <-|- (mult @(-->) @(:*:) @(:+:) ! (x :*: y))

instance (Covariant (->) (->) t, Covariant (->) (->) t', Semimonoidal (-->) (:*:) (:+:) t, Monoidal (-->) (-->) (:*:) (:+:) t) => Monoidal (-->) (-->) (:*:) (:+:) (t <::> t') where
	unit _ = Straight ! \_ -> TT empty

instance (Covariant (->) (->) t, Semimonoidal (<--) (:*:) (:*:) t, Semimonoidal (<--) (:*:) (:*:) t') => Semimonoidal (<--) (:*:) (:*:) (t <::> t') where
	mult = Flip ! \(TT xys) -> (TT :*: TT <-|-<-|-) . (mult @(<--) !) ! (mult @(<--) !) <-|- xys

instance (Covariant (->) (->) t, Monoidal (<--) (-->) (:*:) (:*:) t, Monoidal (<--) (-->) (:*:) (:*:) t') => Monoidal (<--) (-->) (:*:) (:*:) (t <::> t') where
	unit _ = Flip ! \(TT x) -> Straight (\_ -> extract ! extract x)

instance (Traversable (->) (->) t, Traversable (->) (->) t') => Traversable (->) (->) (t <::> t') where
	f <<- x = TT <-|- f <<-<<- run x

instance (Bindable (->) t, Distributive (->) (->) t, Covariant (->) (->) t', Bindable (->) t') => Bindable (->) (t <::> t') where
	f =<< TT x = TT ! (\i -> (identity =<<) <-|- run . f -<< i) =<< x

instance Monoidal (-->) (-->) (:*:) (:*:) t => Liftable (->) (TT Covariant Covariant t) where
	lift :: Covariant (->) (->) t' => t' ~> t <::> t'
	lift = TT . point

instance Monoidal (<--) (-->) (:*:) (:*:) t => Lowerable (->) (TT Covariant Covariant t) where
	lower :: t <::> t' ~> t'
	lower (TT x) = extract x

instance Covariant (->) (->) t => Hoistable (->) (TT Covariant Covariant t) where
	(/|\) :: t' ~> v -> (t <::> t' ~> t <::> v)
	f /|\ TT x = TT ! f <-|- x