circuits
Safe HaskellNone
LanguageGHC2024

Circuit.Channel

Description

Structural semantics for traced monoidal categories.

This module collects the structural superclass chain Channel → Strength → Traced and all base instances for the standard base arrows (->) and K m. These classes describe the monoidal structure, tensorial strength, and feedback-fixing trace that underlie the syntax in Circuit.Trace.

assoc and assoc' here reassociate rightward and leftward respectively. The monomorphic helpers in Circuit.Tensor have the same names but the opposite directions. Also, slide here is the slide t a (t b c) -> t b (t a c); the symmetric braiding t a b -> t b a lives in Circuit.Tensor as braid. Where both structures exist, slide = assoc' .> tensor braid id .> assoc.

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

Synopsis
  • class Category arr => Channel (t :: k -> k -> k) (arr :: k -> k -> Type) where
    • assoc :: forall (a :: k) (b :: k) (c :: k). arr (t (t a b) c) (t a (t b c))
    • assoc' :: forall (a :: k) (b :: k) (c :: k). arr (t a (t b c)) (t (t a b) c)
    • slide :: forall (a :: k) (b :: k) (c :: k). arr (t a (t b c)) (t b (t a c))
  • class Channel t arr => Strength (t :: k -> k -> k) (arr :: k -> k -> Type) where
    • strength :: forall (b :: k) (c :: k) (a :: k). arr b c -> arr (t a b) (t a c)
  • class Strength t arr => Traced (t :: k -> k -> k) (arr :: k -> k -> Type) where
    • trace :: forall (a :: k) (b :: k) (c :: k). arr (t a b) (t a c) -> arr b c

Documentation

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

A monoidal structure on the tensor t internal to the category arr.

Provides the associator and braiding required to reassociate and braid nested tensor values inside an arrow. This is the structure that traced categories inherit as a superclass.

The previous quantified superclass that stated closure of an object constraint under the tensor has been removed along with the Ob apparatus; composite-object legitimacy is an audit concern.

Methods

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

Reassociate to the right: t (t a b) c -> t a (t b c).

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

Inverse reassociation: t a (t b c) -> t (t a b) c.

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

Swap the two outer positions, leaving the inner payload in place: t a (t b c) -> t b (t a c).

Instances

Instances details
Channel Either Process Source # 
Instance details

Defined in Circuit.Process

Methods

assoc :: Process (Either (Either a b) c) (Either a (Either b c)) Source #

assoc' :: Process (Either a (Either b c)) (Either (Either a b) c) Source #

slide :: Process (Either a (Either b c)) (Either b (Either a c)) Source #

Channel (,) Hyper Source # 
Instance details

Defined in Circuit.Hyper

Methods

assoc :: Hyper ((a, b), c) (a, (b, c)) Source #

assoc' :: Hyper (a, (b, c)) ((a, b), c) Source #

slide :: Hyper (a, (b, c)) (b, (a, c)) Source #

Channel (,) Process Source # 
Instance details

Defined in Circuit.Process

Methods

assoc :: Process ((a, b), c) (a, (b, c)) Source #

assoc' :: Process (a, (b, c)) ((a, b), c) Source #

slide :: Process (a, (b, c)) (b, (a, c)) Source #

Channel (,) Pullback Source #

Cartesian channel plumbing for pullbacks.

Instance details

Defined in Circuit.Pullback

Methods

assoc :: Pullback ((a, b), c) (a, (b, c)) Source #

assoc' :: Pullback (a, (b, c)) ((a, b), c) Source #

slide :: Pullback (a, (b, c)) (b, (a, c)) Source #

(Category arr, Channel t arr) => Channel (t :: Type -> Type -> Type) (AlgCat arr :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.Syntax

Methods

assoc :: AlgCat arr (t (t a b) c) (t a (t b c)) Source #

assoc' :: AlgCat arr (t a (t b c)) (t (t a b) c) Source #

slide :: AlgCat arr (t a (t b c)) (t b (t a c)) Source #

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

Cocartesian monoidal structure for K m with Either.

Instance details

Defined in Circuit.Channel

Methods

assoc :: K m (Either (Either a b) c) (Either a (Either b c)) Source #

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

slide :: K m (Either a (Either b c)) (Either b (Either a c)) Source #

Channel Either (->) Source #

Cocartesian monoidal structure for Either.

>>> assoc (Left (Left 1) :: Either (Either Int Bool) Char) :: Either Int (Either Bool Char)
Left 1
>>> assoc' (Left 1 :: Either Int (Either Bool Char)) :: Either (Either Int Bool) Char
Left (Left 1)
>>> slide (Left 1 :: Either Int (Either Bool Char)) :: Either Bool (Either Int Char)
Right (Left 1)
Instance details

Defined in Circuit.Channel

Methods

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

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

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

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

Inclusive monoidal structure for K m with These.

Instance details

Defined in Circuit.Channel

Methods

assoc :: K m (These (These a b) c) (These a (These b c)) Source #

assoc' :: K m (These a (These b c)) (These (These a b) c) Source #

slide :: K m (These a (These b c)) (These b (These a c)) Source #

Channel These (->) Source #

Inclusive monoidal structure for These.

These sits above both (,) and Either: This is the residual-only branch, That is the payload-only branch, and These carries both.

Instance details

Defined in Circuit.Channel

Methods

assoc :: These (These a b) c -> These a (These b c) Source #

assoc' :: These a (These b c) -> These (These a b) c Source #

slide :: These a (These b c) -> These b (These a c) Source #

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

Cartesian monoidal structure for K m with (,).

Instance details

Defined in Circuit.Channel

Methods

assoc :: K m ((a, b), c) (a, (b, c)) Source #

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

slide :: K m (a, (b, c)) (b, (a, c)) Source #

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

Defined in Circuit.Hyper

Methods

assoc :: HyperA (K m) ((a, b), c) (a, (b, c)) Source #

assoc' :: HyperA (K m) (a, (b, c)) ((a, b), c) Source #

slide :: HyperA (K m) (a, (b, c)) (b, (a, c)) Source #

Channel (,) (->) Source #

Cartesian monoidal structure for (,).

>>> assoc ((1, 2), 3) :: (Int, (Int, Int))
(1,(2,3))
>>> assoc' (1, (2, 3)) :: ((Int, Int), Int)
((1,2),3)
>>> (assoc .> assoc') ((1, 2), 3) :: ((Int, Int), Int)
((1,2),3)
>>> slide (1, (2, 3)) :: (Int, (Int, Int))
(2,(1,3))
Instance details

Defined in Circuit.Channel

Methods

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

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

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

(Category arr, Channel t arr) => Channel (t :: Type -> Type -> Type) (SMC w arr :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.SMC

Methods

assoc :: SMC w arr (t (t a b) c) (t a (t b c)) Source #

assoc' :: SMC w arr (t a (t b c)) (t (t a b) c) Source #

slide :: SMC w arr (t a (t b c)) (t b (t a c)) Source #

(Category arr, Channel t arr) => Channel (t :: Type -> Type -> Type) (Trace t arr :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.Trace

Methods

assoc :: Trace t arr (t (t a b) c) (t a (t b c)) Source #

assoc' :: Trace t arr (t a (t b c)) (t (t a b) c) Source #

slide :: Trace t arr (t a (t b c)) (t b (t a c)) Source #

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

Defined in Circuit.Dagger

Methods

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

assoc' :: forall (a :: k) (b :: k) (c :: k). Dagger arr (t a (t b c)) (t (t a b) c) Source #

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

Channel t arr => Channel (t :: k -> k -> k) (Free arr :: k -> k -> Type) Source #

Lift the Channel structure through Free.

Instance details

Defined in Circuit.Layer

Methods

assoc :: forall (a :: k) (b :: k) (c :: k). Free arr (t (t a b) c) (t a (t b c)) Source #

assoc' :: forall (a :: k) (b :: k) (c :: k). Free arr (t a (t b c)) (t (t a b) c) Source #

slide :: forall (a :: k) (b :: k) (c :: k). Free arr (t a (t b c)) (t b (t a c)) Source #

class Channel t arr => Strength (t :: k -> k -> k) (arr :: k -> k -> Type) where Source #

Tensorial strength for a tensor t inside a category arr.

strength tensors a plain morphism with the ambient channel. It is not a syntactic inverse of trace; it is the strength ("tensorial strength") of the tensor t acting on morphisms.

Methods

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

Instances

Instances details
Strength Either Process Source # 
Instance details

Defined in Circuit.Process

Methods

strength :: Process b c -> Process (Either a b) (Either a c) Source #

Strength (,) Hyper Source # 
Instance details

Defined in Circuit.Hyper

Methods

strength :: Hyper b c -> Hyper (a, b) (a, c) Source #

Strength (,) Process Source # 
Instance details

Defined in Circuit.Process

Methods

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

Strength (,) Pullback Source # 
Instance details

Defined in Circuit.Pullback

Methods

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

(Category arr, Strength t arr) => Strength (t :: Type -> Type -> Type) (AlgCat arr :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.Syntax

Methods

strength :: AlgCat arr b c -> AlgCat arr (t a b) (t a c) Source #

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

Traced for K m with the Either tensor, for any Monad m.

Iterates by feeding Left back into the step function until a Right is produced. Uses plain recursion — builds stack proportional to iteration count.

>>> :{
let countTo target = K $ \case
      Left n | n < target -> pure (Left (n + 1))
             | otherwise  -> pure (Right n)
      Right ()            -> pure (Left 0)
:}
>>> runK (trace (countTo (3 :: Int))) ()
3

This instance is OVERLAPPABLE: the IO-specific instance below takes priority for IO, providing constant-stack iteration via delimited continuations.

Instance details

Defined in Circuit.Channel

Methods

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

Strength Either (->) Source #

Either tensorial strength for Either.

strength is the functorial action under Either.

Instance details

Defined in Circuit.Channel

Methods

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

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

Inclusive tensorial strength for K m with These.

Instance details

Defined in Circuit.Channel

Methods

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

Strength These (->) Source #

Inclusive tensorial strength for These.

strength applies the payload morphism to the That branch and the These branch, leaving the This residual branch untouched.

Instance details

Defined in Circuit.Channel

Methods

strength :: (b -> c) -> These a b -> These a c Source #

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

Traced for K m with the cartesian tensor, requiring MonadFix m.

The lazy knot is tied via mfix. The feedback channel is lazy in the recursive binding — the body must not force the feedback value before producing it, or mfix will diverge (just as the pure (,) trace black-holes on strict fields).

>>> :{
let fibs = K $ \(fibs, ()) ->
      pure (0 : 1 : zipWith (+) fibs (drop 1 fibs), take 3 fibs)
:}
>>> runK (trace fibs) ()
[0,1,1]
Instance details

Defined in Circuit.Channel

Methods

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

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

Defined in Circuit.Hyper

Methods

strength :: HyperA (K m) b c -> HyperA (K m) (a, b) (a, c) Source #

Strength (,) (->) Source #

Cartesian tensorial strength for (,).

The implementation uses explicit projections so that the result pair constructor exists before the feedback channel is forced; this keeps fused yank bodies productive even when the body has a strict top-level pattern on the recursive channel.

>>> strength (+1) (error "forced" :: (Int, Int)) `seq` ()
()
Instance details

Defined in Circuit.Channel

Methods

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

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

Defined in Circuit.SMC

Methods

strength :: SMC w arr b c -> SMC w arr (t a b) (t a c) Source #

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

Defined in Circuit.Trace

Methods

strength :: Trace t arr b c -> Trace t arr (t a b) (t a c) Source #

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

Defined in Circuit.Dagger

Methods

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

Strength t arr => Strength (t :: k -> k -> k) (Free arr :: k -> k -> Type) Source #

Lift the Strength class through Free.

A morphism is frozen before tensoring with the feedback channel.

Instance details

Defined in Circuit.Layer

Methods

strength :: forall (b :: k) (c :: k) (a :: k). Free arr b c -> Free arr (t a b) (t a c) Source #

class Strength t arr => Traced (t :: k -> k -> k) (arr :: k -> k -> Type) where Source #

A trace over a morphism arr and tensor t.

trace closes the feedback loop, eliminating the tensor channel. It extends the Strength structure with the feedback-fixing operation.

Object constraints on the feedback channel (a) used to let constrained categories instance this class lawfully; those constraints are now explicit at the instance site rather than inherited from a constraint family.

Law note: the traced-category Sliding axiom is restricted in the premonoidal setting. Benton & Hyland, "Traced Premonoidal Categories" (2003, Def 3.2) replace unrestricted Sliding with Central Sliding: a morphism g may slide past the trace only when g is central. Dually, Centre Preservation says trace f is central whenever f is. This class does not enforce the side-conditions at the type level; lawful instances must guarantee them by construction. See the circuits-axioma sliding oracles for witnesses that the side-condition is not vacuous.

Methods

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

Instances

Instances details
Traced Either Process Source # 
Instance details

Defined in Circuit.Process

Methods

trace :: Process (Either a b) (Either a c) -> Process b c Source #

Traced (,) Hyper Source # 
Instance details

Defined in Circuit.Hyper

Methods

trace :: Hyper (a, b) (a, c) -> Hyper b c Source #

Traced (,) Process Source # 
Instance details

Defined in Circuit.Process

Methods

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

Traced (,) Pullback Source #

The cartesian trace for pullbacks.

The body is a linear map f :: (x, c) -> (x, b). The traced pullback c -> b solves the affine feedback equation in cotangent space:

(dx, db) = f (dx, dc)

solved by the same lazy knot that a differentiable arrow uses. For strict carriers with nonzero channel self-coupling this diverges, exactly as the lazy differentiable trace does. Unlike the differentiable case, though, the equation here is always affinePullback arrows are linear by construction — so a knot over a star-semiring carrier can be eliminated outright rather than iterated.

>>> let body = Pullback (\(dx', dc) -> (2.0 * dc, dx')) :: Pullback (Double, Double) (Double, Double)
>>> runPullback (trace body) 1.0
2.0
Instance details

Defined in Circuit.Pullback

Methods

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

(Category arr, Traced t arr) => Traced (t :: Type -> Type -> Type) (AlgCat arr :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.Syntax

Methods

trace :: AlgCat arr (t a b) (t a c) -> AlgCat arr b c Source #

Traced Either (K IO) Source #

Traced for K IO with Either tensor.

Each iteration re-establishes the prompt boundary. When control0 fires on Left a, it captures the continuation, wraps it around the next loop step, and jumps back to the prompt — constant stack.

>>> :{
let exit42 = K $ \case
      Right () -> pure (Right (42 :: Int))
:}
>>> runK (trace exit42) ()
42
Instance details

Defined in Circuit.Channel

Methods

trace :: K IO (Either a b) (Either a c) -> K IO b c Source #

Monad m => Traced Either (K m :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.Channel

Methods

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

Traced Either (->) Source #

The Either trace iterates: Left feeds back (continue), Right terminates (exit). A compact, under-appreciated pattern for loops in Haskell.

>>> :{
let fac (n, acc) | n <= 1    = Right acc
                 | otherwise = Left (n - 1, n * acc)
:}
>>> trace (either fac fac) (5, 1 :: Int)
120
>>> :{
let countdown = \case
      Left n | n > 0 -> Left (n - 1)
             | otherwise -> Right n
      Right n | n > 0 -> Left (n - 1)
              | otherwise -> Right n
:}
>>> trace countdown (3 :: Int)
0

Vanishing (a): tracing over the unit does nothing.

The unit is Void for the Either tensor. The unitor laws say that threading a plain payload through the unit channel is the same as applying the payload morphism directly.

>>> let f = (+1) :: Int -> Int
>>> trace (unitl' . f . unitl :: Either Void Int -> Either Void Int) 5
6
>>> trace ((unitl' . (+ 3) . unitl) :: Either Void Int -> Either Void Int) 0
3

Yanking: tracing a braid is the identity.

>>> :{
let swapEither (Left x)  = Right x
    swapEither (Right x) = Left x
:}
>>> trace swapEither 42
42
>>> trace ((\e -> case e of Left a -> Right a; Right a -> Left a) :: Either Int Int -> Either Int Int) 42
42

Tightening: payload morphisms pass freely through the trace.

>>> let f = fmap ((+1) :: Int -> Int) . fmap ((*2) :: Int -> Int)
>>> trace (f :: Either Void Int -> Either Void Int) 5
11
>>> trace (fmap ((+1) :: Int -> Int) . fmap ((*2) :: Int -> Int) :: Either Void Int -> Either Void Int) 5
11
Instance details

Defined in Circuit.Channel

Methods

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

MonadFix m => Traced (,) (K m :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.Channel

Methods

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

MonadFix m => Traced (,) (HyperA (K m) :: Type -> Type -> Type) Source # 
Instance details

Defined in Circuit.Hyper

Methods

trace :: HyperA (K m) (a, b) (a, c) -> HyperA (K m) b c Source #

Traced (,) (->) Source #

The cartesian trace ties a lazy knot: the feedback value a and output c are produced simultaneously in a single recursive binding.

Only works in a lazy setting — the feedback value is a self-referential thunk. In a strict language this binding is circular and divergent. Haskell's lazy evaluation makes cyclic sharing possible without an explicit fixpoint operator.

>>> :{
let powers (ns, ()) =
      (1 : map (*2) ns, take 5 ns)
:}
>>> trace powers () :: [Integer]
[1,2,4,8,16]
>>> trace (\(acc, x) -> (acc, x + 1)) 5
6

Vanishing (a): tracing over the unit does nothing.

The unit is () for the (,) tensor. The unitor laws say that threading a plain payload through the unit channel is the same as applying the payload morphism directly.

>>> let f = (+1) :: Int -> Int
>>> trace (unitl' . f . unitl :: ((), Int) -> ((), Int)) 5
6
>>> trace ((unitl' . (+ 3) . unitl) :: ((), Int) -> ((), Int)) 0
3

Yanking: tracing a braid is the identity.

>>> let braid (x, y) = (y, x)
>>> trace braid 42
42
>>> trace ((\(a, b) -> (b, a)) :: (Int, Int) -> (Int, Int)) 42
42

Tightening: payload morphisms pass freely through the trace.

>>> let f (x, a) = (x, a)
>>> trace ((\(x, a) -> (x, a + 1)) . f . (\(x, a) -> (x, a * 2))) 5
11

Sliding: a morphism on the channel slides from one side to the other.

>>> let braid (x, y) = (y, x)
>>> trace ((\(a, b) -> (b, a + 1)) . (\(a, b) -> (b, a)) :: (Int, Int) -> (Int, Int)) 5
6
>>> trace ((\(a, b) -> (b + 1, a)) :: (Int, Int) -> (Int, Int)) 5
6

Strength: an independent payload wire is invisible to the trace.

>>> let f (x, c) = (x, c + 1)
>>> let g (x, (a, c)) = (x', (a * 2, d)) where (x', d) = f (x, c)
>>> trace g (3, 5)
(6,6)
>>> trace ((\(x, (p, q)) -> (x, (p + 7, q + 1))) :: (Int, (Int, Int)) -> (Int, (Int, Int))) (0, 5)
(7,6)
Instance details

Defined in Circuit.Channel

Methods

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

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

Defined in Circuit.SMC

Methods

trace :: SMC w arr (t a b) (t a c) -> SMC w arr b c Source #

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

Defined in Circuit.Trace

Methods

trace :: Trace t arr (t a b) (t a c) -> Trace t arr b c Source #

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

Defined in Circuit.Dagger

Methods

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

Traced t arr => Traced (t :: k -> k -> k) (Free arr :: k -> k -> Type) Source #

Lift the Traced class through Free.

A loop body in Free arr is frozen before calling the base trace.

Instance details

Defined in Circuit.Layer

Methods

trace :: forall (a :: k) (b :: k) (c :: k). Free arr (t a b) (t a c) -> Free arr b c Source #