circuits
Safe HaskellNone
LanguageGHC2024

Circuit.Tensor

Description

Tensor action and braiding for traced categories.

This module collects the cartesian and cocartesian structure over the standard tensors (,) and Either, plus the tensor action on morphisms.

The goal is to keep the core Trace syntax and eval fold independent of these structural details.

Note: the monomorphic assocL and assocR helpers below reassociate leftward and rightward respectively — the opposite direction to assoc and assoc'.

Tensor / Action are kind-polymorphic.

Synopsis

Fused parallel composition

superpose :: forall t (arr :: Type -> Type -> Type) a b c d. (Tensor t arr, Traced t arr) => Trace t arr a b -> Trace t arr c d -> Trace t arr (t a c) (t b d) Source #

Fused parallel composition for Trace when the feedback tensor matches.

Two yanks in parallel superpose into one yank over a paired channel, satisfying the superposing axiom of traced monoidal categories:

superpose (trace f) (trace g) = trace (pre . tensor f g . post)

where pre and post rearrange the paired channel via associators and braiding. This preserves sharing for recursive circuits; the lawful Tensor instance falls back to independent evaluation.

>>> let k1 = yank (base (\(ns, _) -> (1 : ns, take 3 ns))) :: Trace (,) (->) [Int] [Int]
>>> let k2 = yank (base (\(ns, _) -> (2 : ns, take 3 ns)))
>>> eval (superpose k1 k2) ([], [])
([1,1,1],[2,2,2])

The same fusion works for K, preserving sharing across the recursive channels under MonadFix.

>>> let k1 = yank (base (K $ \(ns, _) -> pure (1 : ns, take 3 ns))) :: Trace (,) (K Identity) [Int] [Int]
>>> let k2 = yank (base (K $ \(ns, _) -> pure (2 : ns, take 3 ns)))
>>> runK (eval (superpose k1 k2)) ([], [])
Identity ([1,1,1],[2,2,2])

Schedule bias (also used by additive disjunction)

data Bias Source #

Bias for ordered choice in scheduling and additive disjunction.

LeftFirst and RightFirst are used by shared-medium fusion in Circuit.Shared and by additive disjunction in Circuit.Poles.

Constructors

LeftFirst 
RightFirst 

Instances

Instances details
Eq Bias Source # 
Instance details

Defined in Circuit.Tensor

Methods

(==) :: Bias -> Bias -> Bool #

(/=) :: Bias -> Bias -> Bool #

Show Bias Source # 
Instance details

Defined in Circuit.Tensor

Methods

showsPrec :: Int -> Bias -> ShowS #

show :: Bias -> String #

showList :: [Bias] -> ShowS #

Channel product on base arrows

type family Unit (t :: k -> k -> k) :: k Source #

The unit object for a tensor t.

t is an object-level bifunctor (Either, (,), type-level (+), …) with kind k -> k -> k, not a morphism tensor.

Instances

Instances details
type Unit Either Source # 
Instance details

Defined in Circuit.Tensor

type Unit These Source # 
Instance details

Defined in Circuit.Tensor

type Unit These = Void
type Unit (,) Source # 
Instance details

Defined in Circuit.Tensor

type Unit (,) = ()

class Category arr => Unital (t :: k -> k -> k) (arr :: k -> k -> Type) where Source #

The unit object structure of a tensor t on a category arr.

unitl and unitr witness that the tensor has a unit object. This is the planar fragment without the morphism-level tensor product: arrows that are merely unital can introduce and eliminate the unit, but cannot parallel-compose two arbitrary morphisms.

Splitting this out from Tensor matters for premonoidal arrows such as Circuit.Prob: the unitors are deterministic and embed cleanly, while the general tensor product tensor is not canonical.

Kind-polymorphic: t and arr share object kind (inferred via PolyKinds).

Methods

unitl :: forall (a :: k). arr (t (Unit t) a) a Source #

Left unitor: I ⊗ a -> a.

unitl' :: forall (a :: k). arr a (t (Unit t) a) Source #

Inverse left unitor: a -> I ⊗ a.

unitr :: forall (a :: k). arr (t a (Unit t)) a Source #

Right unitor: a ⊗ I -> a.

unitr' :: forall (a :: k). arr a (t a (Unit t)) Source #

Inverse right unitor: a -> a ⊗ I.

Instances

Instances details
Unital (,) Process Source # 
Instance details

Defined in Circuit.Process

Unital (,) Pullback Source #

Parallel composition pairs pullbacks independently; braid swaps the two cotangents.

>>> let f = Pullback (+1) :: Pullback Int Int
>>> let g = Pullback (*2) :: Pullback Int Int
>>> runPullback (tensor f g) (3, 4)
(4,8)
Instance details

Defined in Circuit.Pullback

Monad m => Unital Either (K m :: Type -> Type -> Type) Source #

Coproduct unit structure on K m.

Instance details

Defined in Circuit.Tensor

Methods

unitl :: K m (Either (Unit Either) a) a Source #

unitl' :: K m a (Either (Unit Either) a) Source #

unitr :: K m (Either a (Unit Either)) a Source #

unitr' :: K m a (Either a (Unit Either)) Source #

Unital Either (->) Source #

Coproduct unit structure on functions.

Laws: unitl eliminates Left, unitl' injects Right; unitr eliminates Right, unitr' injects Left.

Instance details

Defined in Circuit.Tensor

Monad m => Unital These (K m :: Type -> Type -> Type) Source #

Inclusive unit structure on K m.

Instance details

Defined in Circuit.Tensor

Methods

unitl :: K m (These (Unit These) a) a Source #

unitl' :: K m a (These (Unit These) a) Source #

unitr :: K m (These a (Unit These)) a Source #

unitr' :: K m a (These a (Unit These)) Source #

Unital These (->) Source #

Inclusive unit structure on functions.

Laws: unitl eliminates a vacuous This, unitl' injects with That; unitr eliminates a vacuous That, unitr' injects with This.

Instance details

Defined in Circuit.Tensor

Methods

unitl :: These (Unit These) a -> a Source #

unitl' :: a -> These (Unit These) a Source #

unitr :: These a (Unit These) -> a Source #

unitr' :: a -> These a (Unit These) Source #

Monad m => Unital (,) (K m :: Type -> Type -> Type) Source #

Cartesian unit structure on K (effectful sequential product).

Instance details

Defined in Circuit.Tensor

Methods

unitl :: K m (Unit (,), a) a Source #

unitl' :: K m a (Unit (,), a) Source #

unitr :: K m (a, Unit (,)) a Source #

unitr' :: K m a (a, Unit (,)) Source #

Unital (,) (->) Source #

Cartesian unit structure on functions.

Laws: unitl = snd, unitl' = ((),), unitr = fst, unitr' = (,) ().

Instance details

Defined in Circuit.Tensor

Methods

unitl :: (Unit (,), a) -> a Source #

unitl' :: a -> (Unit (,), a) Source #

unitr :: (a, Unit (,)) -> a Source #

unitr' :: a -> (a, Unit (,)) Source #

Unital t arr => Unital (t :: Type -> Type -> Type) (Trace t' arr :: Type -> Type -> Type) Source #

Lift Unital through Trace.

Instance details

Defined in Circuit.Tensor

Methods

unitl :: Trace t' arr (t (Unit t) a) a Source #

unitl' :: Trace t' arr a (t (Unit t) a) Source #

unitr :: Trace t' arr (t a (Unit t)) a Source #

unitr' :: Trace t' arr a (t a (Unit t)) Source #

Unital w arr => Unital (w :: Type -> Type -> Type) (SMC w arr :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.SMC

Methods

unitl :: SMC w arr (w (Unit w) a) a Source #

unitl' :: SMC w arr a (w (Unit w) a) Source #

unitr :: SMC w arr (w a (Unit w)) a Source #

unitr' :: SMC w arr a (w a (Unit w)) Source #

Unital t arr => Unital (t :: k -> k -> k) (Dagger arr :: k -> k -> Type) Source # 
Instance details

Defined in Circuit.Dagger

Methods

unitl :: forall (a :: k). Dagger arr (t (Unit t) a) a Source #

unitl' :: forall (a :: k). Dagger arr a (t (Unit t) a) Source #

unitr :: forall (a :: k). Dagger arr (t a (Unit t)) a Source #

unitr' :: forall (a :: k). Dagger arr a (t a (Unit t)) Source #

class Unital t arr => Tensor (t :: k -> k -> k) (arr :: k -> k -> Type) where Source #

The tensor action of t on a category arr, without braiding.

tensor is the tensor product of morphisms (parallel composition on disjoint wires). The unitors live in the Unital superclass.

Kind-polymorphic: t and arr share object kind (inferred via PolyKinds).

Methods

tensor :: forall (a :: k) (b :: k) (c :: k) (d :: k). arr a b -> arr c d -> arr (t a c) (t b d) Source #

Parallel composition: run two arrows on disjoint wires.

>>> tensor ((+1) :: Int -> Int) ((*2) :: Int -> Int) (3, 4)
(4,8)

Instances

Instances details
Tensor (,) Process Source # 
Instance details

Defined in Circuit.Process

Methods

tensor :: Process a b -> Process c d -> Process (a, c) (b, d) Source #

Tensor (,) Pullback Source # 
Instance details

Defined in Circuit.Pullback

Methods

tensor :: Pullback a b -> Pullback c d -> Pullback (a, c) (b, d) Source #

Monad m => Tensor Either (K m :: Type -> Type -> Type) Source #

Coproduct tensor action on K m.

>>> import Circuit.Category (K(..), runK)
>>> let f = K (\n -> pure (n + 1)) :: K IO Int Int
>>> let g = K (\n -> pure (n * 2)) :: K IO Int Int
>>> runK (tensor f g) (Left 3 :: Either Int Int)
Left 4
>>> runK (tensor f g) (Right 3 :: Either Int Int)
Right 6
Instance details

Defined in Circuit.Tensor

Methods

tensor :: K m a b -> K m c d -> K m (Either a c) (Either b d) Source #

Tensor Either (->) Source #

Coproduct tensor action on functions.

>>> tensor ((+1) :: Int -> Int) ((*2) :: Int -> Int) (Left 3 :: Either Int Int)
Left 4
>>> tensor ((+1) :: Int -> Int) ((*2) :: Int -> Int) (Right 3 :: Either Int Int)
Right 6
Instance details

Defined in Circuit.Tensor

Methods

tensor :: (a -> b) -> (c -> d) -> Either a c -> Either b d Source #

Monad m => Tensor These (K m :: Type -> Type -> Type) Source #

Inclusive tensor action on K m.

Instance details

Defined in Circuit.Tensor

Methods

tensor :: K m a b -> K m c d -> K m (These a c) (These b d) Source #

Tensor These (->) Source #

Inclusive tensor action on functions.

Instance details

Defined in Circuit.Tensor

Methods

tensor :: (a -> b) -> (c -> d) -> These a c -> These b d Source #

Monad m => Tensor (,) (K m :: Type -> Type -> Type) Source #

Cartesian tensor on K (effectful sequential product).

Instance details

Defined in Circuit.Tensor

Methods

tensor :: K m a b -> K m c d -> K m (a, c) (b, d) Source #

Tensor (,) (->) Source #

Cartesian tensor action on functions.

Instance details

Defined in Circuit.Tensor

Methods

tensor :: (a -> b) -> (c -> d) -> (a, c) -> (b, d) Source #

(Tensor t arr, Traced t' arr) => Tensor (t :: Type -> Type -> Type) (Trace t' arr :: Type -> Type -> Type) Source #

Lift Tensor/Action through Trace.

This is the single lawful instance: it evaluates each Trace branch independently with eval and combines the results using the base arrow's tensor. It is correct and black-hole-free, but does not fuse feedback loops. For the fused superposition of two yanks, use superpose.

Instance details

Defined in Circuit.Tensor

Methods

tensor :: Trace t' arr a b -> Trace t' arr c d -> Trace t' arr (t a c) (t b d) Source #

Tensor w arr => Tensor (w :: Type -> Type -> Type) (SMC w arr :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.SMC

Methods

tensor :: SMC w arr a b -> SMC w arr c d -> SMC w arr (w a c) (w b d) Source #

Tensor t arr => Tensor (t :: k -> k -> k) (Dagger arr :: k -> k -> Type) Source # 
Instance details

Defined in Circuit.Dagger

Methods

tensor :: forall (a :: k) (b :: k) (c :: k) (d :: k). Dagger arr a b -> Dagger arr c d -> Dagger arr (t a c) (t b d) Source #

class Tensor t arr => Action (t :: k -> k -> k) (arr :: k -> k -> Type) where Source #

The action of a tensor t on a category arr, extended with a symmetric braiding.

This is the self-action of a symmetric monoidal category: t acts on arr by taking morphisms to morphisms over paired objects, and braid provides the symmetry.

Methods

braid :: forall (a :: k) (b :: k). arr (t a b) (t b a) Source #

Symmetric braiding.

>>> braid (3, 4) :: (Int, Int)
(4,3)

Instances

Instances details
Action (,) Process Source # 
Instance details

Defined in Circuit.Process

Methods

braid :: Process (a, b) (b, a) Source #

Action (,) Pullback Source # 
Instance details

Defined in Circuit.Pullback

Methods

braid :: Pullback (a, b) (b, a) Source #

Monad m => Action Either (K m :: Type -> Type -> Type) Source #

Coproduct symmetry on K m.

Instance details

Defined in Circuit.Tensor

Methods

braid :: K m (Either a b) (Either b a) Source #

Action Either (->) Source #

Coproduct symmetry on functions.

>>> braid (Left 3 :: Either Int Int) :: Either Int Int
Right 3
Instance details

Defined in Circuit.Tensor

Methods

braid :: Either a b -> Either b a Source #

Monad m => Action These (K m :: Type -> Type -> Type) Source #

Inclusive symmetry on K m.

Instance details

Defined in Circuit.Tensor

Methods

braid :: K m (These a b) (These b a) Source #

Action These (->) Source #

Inclusive symmetry on functions.

Instance details

Defined in Circuit.Tensor

Methods

braid :: These a b -> These b a Source #

Monad m => Action (,) (K m :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.Tensor

Methods

braid :: K m (a, b) (b, a) Source #

Action (,) (->) Source #

Cartesian symmetry on functions.

Instance details

Defined in Circuit.Tensor

Methods

braid :: (a, b) -> (b, a) Source #

(Action t arr, Traced t' arr) => Action (t :: Type -> Type -> Type) (Trace t' arr :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.Tensor

Methods

braid :: Trace t' arr (t a b) (t b a) Source #

Action w arr => Action (w :: Type -> Type -> Type) (SMC w arr :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.SMC

Methods

braid :: SMC w arr (w a b) (w b a) Source #

Action t arr => Action (t :: k -> k -> k) (Dagger arr :: k -> k -> Type) Source # 
Instance details

Defined in Circuit.Dagger

Methods

braid :: forall (a :: k) (b :: k). Dagger arr (t a b) (t b a) Source #

class TensorSeed (t :: Type -> Type -> Type) where Source #

Value-level pairing for a tensor t.

Tensor gives the action of t on morphisms; TensorSeed names the canonical way to combine two values into a value of type t a b. It is needed by constructions (such as SomeBody) that store a concrete channel value alongside a body.

Not every tensor has a canonical pairing: (,) has the pair constructor, but Either has no unbiased way to combine a and b into Either a b. Consequently TensorSeed is a separate class.

Methods

seedPair :: a -> b -> t a b Source #

Instances

Instances details
TensorSeed (,) Source #

Cartesian pairing.

Instance details

Defined in Circuit.Tensor

Methods

seedPair :: a -> b -> (a, b) Source #

Distributivity of two tensors (multiplicative over additive)

class (Tensor d arr, Tensor t arr) => Distributive (d :: k -> k -> k) (t :: k -> k -> k) (arr :: k -> k -> Type) where Source #

Distributivity of a multiplicative tensor d over an additive tensor t.

In a distributive monoidal category the product distributes over the sum: d a (t b c) ≅ t (d a b) (d a c) and d (t a b) c ≅ t (d a c) (d b c), and the additive unit is annihilated: d a (Unit t) ≅ Unit t.

For d = (,) and t = Either this is the ordinary distributivity of cartesian product over coproduct, with (a, Void) ≅ Void.

Methods

distl :: forall (a :: k) (b :: k) (c :: k). arr (d a (t b c)) (t (d a b) (d a c)) Source #

Left distributor: d a (t b c) -> t (d a b) (d a c).

distl' :: forall (a :: k) (b :: k) (c :: k). arr (t (d a b) (d a c)) (d a (t b c)) Source #

Inverse left distributor.

distr :: forall (a :: k) (b :: k) (c :: k). arr (d (t a b) c) (t (d a c) (d b c)) Source #

Right distributor: d (t a b) c -> t (d a c) (d b c).

distr' :: forall (a :: k) (c :: k) (b :: k). arr (t (d a c) (d b c)) (d (t a b) c) Source #

Inverse right distributor.

annih :: forall (a :: k). arr (d a (Unit t)) (Unit t) Source #

Left annihilator: d a (Unit t) -> Unit t.

annih' :: forall (a :: k). arr (Unit t) (d a (Unit t)) Source #

Inverse left annihilator.

Instances

Instances details
Monad m => Distributive (,) Either (K m :: Type -> Type -> Type) Source #

Distributivity of (,) over Either on K m.

Instance details

Defined in Circuit.Tensor

Methods

distl :: K m (a, Either b c) (Either (a, b) (a, c)) Source #

distl' :: K m (Either (a, b) (a, c)) (a, Either b c) Source #

distr :: K m (Either a b, c) (Either (a, c) (b, c)) Source #

distr' :: K m (Either (a, c) (b, c)) (Either a b, c) Source #

annih :: K m (a, Unit Either) (Unit Either) Source #

annih' :: K m (Unit Either) (a, Unit Either) Source #

Distributive (,) Either (->) Source #

Distributivity of (,) over Either on functions.

>>> distl ('x', Left 1 :: Either Int Bool) :: Either (Char, Int) (Char, Bool)
Left ('x',1)
>>> distl ('x', Right True) :: Either (Char, Int) (Char, Bool)
Right ('x',True)
Instance details

Defined in Circuit.Tensor

Methods

distl :: (a, Either b c) -> Either (a, b) (a, c) Source #

distl' :: Either (a, b) (a, c) -> (a, Either b c) Source #

distr :: (Either a b, c) -> Either (a, c) (b, c) Source #

distr' :: Either (a, c) (b, c) -> (Either a b, c) Source #

annih :: (a, Unit Either) -> Unit Either Source #

annih' :: Unit Either -> (a, Unit Either) Source #

Cartesian / cocartesian associators

assocL :: (a, (b, c)) -> ((a, b), c) Source #

Leftward associator: (a, (b, c)) -> ((a, b), c).

assocR :: ((a, b), c) -> (a, (b, c)) Source #

Rightward associator: ((a, b), c) -> (a, (b, c)).

coassoc :: Either a (Either b c) -> Either (Either a b) c Source #

Coassociator for sums.

>>> coassoc (Left 1 :: Either Int (Either Bool Char))
Left (Left 1)

coassoc' :: Either (Either a b) c -> Either a (Either b c) Source #

Inverse coassociator.

>>> coassoc' (Left (Left 1) :: Either (Either Int Bool) Char)
Left 1

coseed :: s -> Either a b -> Either (s, a) (s, b) Source #

Tag a channel value onto whichever branch of the sum is active.

>>> coseed "st" (Left 42 :: Either Int Char)
Left ("st",42)

coabsorbL :: (t -> s -> s') -> Either (s, (t, a)) b -> Either (s', a) b Source #

If the left branch is taken, move a value from the payload into the channel wire.

>>> coabsorbL (+) (Left (10, (3, 7)) :: Either (Int, (Int, Int)) Bool)
Left (13,7)

coabsorbR :: (t -> s -> s') -> Either a (s, (t, b)) -> Either a (s', b) Source #

If the right branch is taken, move a value from the payload into the channel wire.

>>> coabsorbR (+) (Right (10, (3, 7)) :: Either Bool (Int, (Int, Int)))
Right (13,7)

coreleaseL :: (s -> (s', t)) -> Either (s, a) b -> Either (s', (t, a)) b Source #

If the left branch is taken, move a value from the channel wire into the payload.

>>> coreleaseL (\s -> (s+1, s*2)) (Left (5, 99) :: Either (Int, Int) Char)
Left (6,(10,99))

coreleaseR :: (s -> (s', t)) -> Either a (s, b) -> Either a (s', (t, b)) Source #

If the right branch is taken, move a value from the channel wire into the payload.

>>> coreleaseR (\s -> (s+1, s*2)) (Right (5, 99) :: Either Char (Int, Int))
Right (6,(10,99))