packages feed

linear-smc-2.2.2: Control/Category/StructuredObject.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE UnicodeSyntax #-}

module Control.Category.StructuredObject where

import Control.Category.Constrained
import Prelude hiding (id, (.))
import Data.Array (Ix)
import Data.Constraint (Dict(..),Constraint)

-- representation for the objects
data Repr s a where
  RUnit :: Repr s ()
  RPair :: Repr s a -> Repr s b -> Repr s (a,b)
  RAtom :: Repr s (Atom s)
  RDual :: Repr s a -> Repr s (Dual a)

-----------------
-- OO
class OO s a where
  type Sub s t a
  getRepr :: Repr s a
  subOO :: forall c b. (OO s a, a ~ (c ⊗ b)) => Dict (OO s c, OO s b)
  subOO = error "not a product"
  dualOO :: forall z. (OO s a, a ~ Dual z) => Dict (OO s z)
  dualOO = error "not a dual"
  toList :: a -> [s]

type Structured s con = forall x. con x => OO s x :: Constraint

type Basic s = (Bounded s, Enum s, Ix s)

instance OO s () where
  type Sub s t () = ()
  getRepr = RUnit
  toList () = []
instance Basic s => OO s (Atom s) where
  type Sub s t (Atom s) = Atom t
  getRepr = RAtom
  toList (Atom x) = [x]
instance OO s a => OO s (Dual a) where
  type Sub s t (Dual a) = Dual (Sub s t a)
  getRepr = RDual getRepr
  dualOO = Dict
  toList (Dual a) = toList a

mapRepr :: forall t s a. Repr s a -> Repr t (Sub s t a)
mapRepr RAtom = RAtom
mapRepr RUnit = RUnit
mapRepr (RPair q r) = RPair (mapRepr q) (mapRepr r)
mapRepr (RDual r) = RDual (mapRepr r)

instance (OO s a, OO s b) => OO s (a⊗b) where
  toList (a,b) = toList a <> toList b
  type Sub s t (a,b) = (Sub s t a,Sub s t b)
  getRepr = RPair getRepr getRepr
  subOO = Dict

instance ProdObj (OO s) where
  prodobj = Dict
  objprod = subOO
  objunit = Dict

instance AutonomousObj (OO s) where
  objDual = Dict
  dualObj :: forall z a con. (z ~ Dual a, con z, con ~ OO s) => Dict (con a)
  dualObj = dualOO @s @z