circuits
Safe HaskellNone
LanguageGHC2024

Circuit

Description

Usage

import Circuit

Lazy feedback (knot-tying)

Use the (,) tensor to tie a lazy knot. The feedback value and output are produced simultaneously.

>>> let powers (ns, ()) = (1 : map (*2) ns, take 5 ns)
>>> trace powers () :: [Integer]
[1,2,4,8,16]

Iteration

Use the Either tensor for loops that terminate.

>>> let step n = if n < 5 then Left (n + 1) else Right n
>>> trace (either step step) (0 :: Int)
5

Switching between representations

Trace is the inspectable free-syntax form. Hyper is the final, coinductive encoding. Convert a Trace to a Hyper with encode, and observe it with observe (or eliminate it with runHyper).

>>> observe (encode (base (+1) :: Trace (,) (->) Int Int)) 41
42

Overview

This library provides three views on feedback:

  • Trace (in Circuit.Trace) — the initial, inspectable free-syntax.
  • Hyper (in Circuit.Hyper) — the final, coinductive encoding.
  • Body (in Circuit.Body) — the knot-body category arr (t ch a) (t ch b), the stateful substrate that Trace hides before tracing. The cartesian instance is `Body (,) ch (->)`.

The Traced class (in Circuit.Channel) abstracts the choice of tensor, supporting lazy knots with (,), iteration with Either, and scheduling with These.

All braided, cartesian, and cocartesian structure, plus the fused parallel composition superpose, lives in Circuit.Tensor.

Core Concepts

  • Tensor (t): The bifunctor pairing a feedback value with a payload inside a Trace (currently @(,), Either, or These for scheduling).
  • Feedback value: The component that travels around the loop (the first parameter of the tensor inside a Trace).
  • Payload: The value being transformed and emitted (the second parameter of the tensor inside a Trace).
  • Feedback channel: The path the feedback value takes when routed back into the next step.

Verb glossary

  • Folds eliminate a free construction: run (any Layer), freeze (Free to its base arrow), melt (Net to Trace), bind (fold into a target category), lower (restrict a fold to the generators).
  • Injections embed one construction into another without eliminating: unit (base arrow into a Layer), base (base arrow into Trace), yank (close a feedback loop in Trace).
  • Representation changes: encode (Trace to Hyper), observe runHyper (Hyper to function fixed point).
Synopsis

Trace (free traced category syntax)

type Trace (t :: Type -> Type -> Type) (arr :: Type -> Type -> Type) = Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigYank t :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type)) arr Source #

Free traced monoidal category over tensor t.

base :: forall arr a b (t :: Type -> Type -> Type). arr a b -> Trace t arr a b Source #

Lift a base arrow into the free traced category.

yank :: forall t (arr :: Type -> Type -> Type) s a b. Trace t arr (t s a) (t s b) -> Trace t arr a b Source #

Close a feedback loop over the channel tensor t.

class Strength t arr => Traced (t :: k -> k -> k) (arr :: k -> k -> Type) 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.

Minimal complete definition

trace

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 #

class Channel t arr => Strength (t :: k -> k -> k) (arr :: k -> k -> Type) 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.

Minimal complete definition

strength

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 #

Close a feedback loop. See Circuit.Channel.

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

Open a feedback loop. See Circuit.Channel.

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

Polynomial channels

data Channel (arr :: Type -> Type -> Type) (p :: Poly) where Source #

A channel whose interface is the polynomial p.

Internally it is a Moore system with hidden state s. The state is existentially quantified so that different channel constructors can use different state types.

Constructors

Ch 

Fields

emitChannel :: forall (p :: Poly). Channel (->) p -> Eval p () Source #

Observe the current output of a (->) channel.

The observation is an Eval p (): a position together with a trivial direction consumer. The position is the channel's current output; the direction consumer is how a future input will advance the channel.

commitChannel :: forall (p :: Poly). Channel (->) p -> Dir p -> Channel (->) p Source #

Commit an input direction to a (->) channel, advancing its state.

idChannel :: a -> Channel (->) (Mono a a) Source #

Identity channel on a monomial interface Mono a a.

Output is the current state; next state is the input direction. An initial state must be supplied because a Moore machine has no input before the first commit.

constChannel :: b -> Channel (->) (Mono a b) Source #

Constant-output channel on a monomial interface Mono a b.

Output is always b; the state is the constant value and is preserved across commits (the input direction is ignored).

mapChannel :: forall (p :: Poly) (q :: Poly). (SystemEval p, SystemEval q) => Morphism p q -> Channel (->) p -> Channel (->) q Source #

Map a polynomial morphism over a (->) channel.

The forward map transforms positions; the backward map transforms directions. This is the functorial action of Morphism on channels.

Body (knot-body category)

newtype Body (t :: k -> k1 -> k2) (ch :: k) (arr :: k2 -> k2 -> Type) (a :: k1) (b :: k1) Source #

A morphism across a tensored channel.

Body t ch arr a b is a morphism arr (t ch a) (t ch b). The channel ch is threaded alongside the payload by the tensor t; it may be state, residual, a stream, or any other value the base arrow arr carries along with the input and output. Composition threads the same channel through both morphisms.

Constructors

Body 

Fields

Instances

Instances details
(Monad m, Pointed s) => HasDual Void (Body Either s (K m) :: Type -> Type -> Type) Source #

Unit poles for Body Either s (K m) at Void.

Instance details

Defined in Circuit.Body

Methods

open :: Poles (Body Either s (K m)) Void Void Source #

Pointed s => HasDual Void (Body Either s (->) :: Type -> Type -> Type) Source #

Unit poles for Body Either s (->) at the unit object Void.

The coproduct case needs a distinguished element of the carrier s: on a Right x input the companion must return Left s for some s, and there is no ambient state to use. Pointed captures exactly that, which is weaker than Monoid. This is the structural pointedness requirement that makes Either differ from (,).

Instance details

Defined in Circuit.Body

Methods

open :: Poles (Body Either s (->)) Void Void Source #

Monad m => HasDual () (Body (,) s (K m) :: Type -> Type -> Type) Source #

Unit poles for Body (,) s (K m).

Same shape as the (->) instance, but the companion returns () in the monad and threads the ambient state through unchanged.

Instance details

Defined in Circuit.Body

Methods

open :: Poles (Body (,) s (K m)) () () Source #

HasDual () (Body (,) s (->) :: Type -> Type -> Type) Source #

Unit poles for Body (,) s (->) at the unit object ().

The companion discards its input and returns (); the conjoint delegates to the companion. Yanking recovers the identity on ().

Instance details

Defined in Circuit.Body

Methods

open :: Poles (Body (,) s (->)) () () Source #

Category arr => Category (Body t ch arr :: k3 -> k3 -> Type) Source # 
Instance details

Defined in Circuit.Body

Methods

id :: forall (a :: k3). Body t ch arr a a Source #

(.) :: forall (b :: k3) (c :: k3) (a :: k3). Body t ch arr b c -> Body t ch arr a b -> Body t ch arr a c Source #

data SomeBody (t :: Type -> k -> k1) (arr :: k1 -> k1 -> Type) (a :: k) (b :: k) where Source #

A Body with its channel type hidden.

Constructors

SomeBody :: forall {k} {k1} ch (t :: Type -> k -> k1) (arr :: k1 -> k1 -> Type) (a :: k) (b :: k). ch -> Body t ch arr a b -> SomeBody t arr a b 

Instances

Instances details
(Strength t arr, Pointed (Unit t), TensorSeed t) => Category (SomeBody t arr :: Type -> Type -> Type) Source #

Category instance for SomeBody.

The carrier of the composite is the tensor of the two carriers, and the stored seed is combined with seedPair. Identity needs a seed at the tensor unit, hence the 'Pointed (Unit t)' requirement. Tensors whose unit is uninhabited (e.g. Either with Unit Either = Void) therefore do not admit an identity; tensors without a canonical value-level pairing (also Either, These) do not admit composition.

Instance details

Defined in Circuit.Body

Methods

id :: SomeBody t arr a a Source #

(.) :: SomeBody t arr b c -> SomeBody t arr a b -> SomeBody t arr a c Source #

cascadeBody :: forall {k} (t :: k -> k -> k) (arr :: k -> k -> Type) (ch' :: k) (b :: k) (c :: k) (ch :: k) (a :: k). Strength t arr => Body t ch' arr b c -> Body t ch arr a b -> Body t (t ch ch') arr a c Source #

Compose two bodies at carriers ch and ch' into a body at carrier t ch ch'. This is the body-level building block of horizontal 2-cell algebra and of the Category instance for SomeBody.

The composite is

  assoc .> slide .> strength f .> slide .> strength g .> assoc'

cascadeSome :: SomeBody (,) (->) b c -> SomeBody (,) (->) a b -> SomeBody (,) (->) a c Source #

Pointed carrier-tensoring composition for t = (,) and arr = (->).

Seeds pair under the tensor, and the composite can be run with runSomeBody. This is the pointed counterpart to the unpointed cascadeBody.

runSomeBody :: SomeBody (,) (->) a b -> [a] -> [b] Source #

Run an existentially-packed cartesian body over a list of inputs.

This is the (,) / list specialisation of SomeBody.

Circ (loose bicategory of bodies with varying carriers)

data Circ (t :: k -> k1 -> k2) (arr :: k2 -> k2 -> Type) (a :: k1) (b :: k1) where Source #

Loose 1-cell: a body with its carrier type hidden.

Constructors

Circ :: forall {k} {k1} {k2} (t :: k -> k1 -> k2) (ch :: k) (arr :: k2 -> k2 -> Type) (a :: k1) (b :: k1). Body t ch arr a b -> Circ t arr a b 

Instances

Instances details
Strength t arr => Category (Circ t arr :: k -> k -> Type) Source #

Category instance for Circ.

The laws hold only up to invertible Sq: on-the-nose associativity and unitality are impossible as Haskell values because the carriers of the two sides differ. Observational witnesses live in Axioma.Circ.

Instance details

Defined in Circuit.Circ

Methods

id :: forall (a :: k). Circ t arr a a Source #

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

idCirc :: forall {k2} (t :: k2 -> k2 -> k2) (arr :: k2 -> k2 -> Type) (a :: k2). Strength t arr => Circ t arr a a Source #

Identity loose 1-cell at the tensor unit carrier.

The carrier is pinned to Unit so that the unit law can be witnessed with the unitor; without the annotation GHC would instantiate the hidden carrier to Any.

data Sq (t :: k2 -> k1 -> k2) (arr :: k2 -> k2 -> Type) (ch :: k2) (ch' :: k2) (a :: k1) (b :: k1) Source #

Square (indexed 2-cell). The carrier maps compose; the middle body must match (a caller side condition).

Constructors

Sq 

Fields

  • carrierMap :: arr ch ch'

    Map between carriers.

  • sqSrc :: Body t ch arr a b

    Source body, over the source carrier.

  • sqTgt :: Body t ch' arr a b

    Target body, over the target carrier.

idSq :: forall {k2} {k1} (arr :: k2 -> k2 -> Type) (t :: k2 -> k1 -> k2) (ch :: k2) (a :: k1) (b :: k1). Category arr => Body t ch arr a b -> Sq t arr ch ch a b Source #

Identity square on a body.

vcomp :: forall {k2} {k1} (arr :: k2 -> k2 -> Type) (t :: k2 -> k1 -> k2) (ch' :: k2) (ch'' :: k2) (a :: k1) (b :: k1) (ch :: k2). Category arr => Sq t arr ch' ch'' a b -> Sq t arr ch ch' a b -> Sq t arr ch ch'' a b Source #

Vertical composition of squares.

The middle body must match; this is a caller side condition.

data Intertwiner (t :: k2 -> k1 -> k2) (arr :: k2 -> k2 -> Type) (a :: k1) (b :: k1) where Source #

Existential closure of Sq, for stating "there exists a 2-cell".

Constructors

Intertwiner :: forall {k2} {k1} (t :: k2 -> k1 -> k2) (arr :: k2 -> k2 -> Type) (ch :: k2) (ch' :: k2) (a :: k1) (b :: k1). Sq t arr ch ch' a b -> Intertwiner t arr a b 

withIntertwiner :: forall {k2} {k1} (t :: k2 -> k1 -> k2) (arr :: k2 -> k2 -> Type) (a :: k1) (b :: k1) r. Intertwiner t arr a b -> (forall (ch :: k2) (ch' :: k2). Sq t arr ch ch' a b -> r) -> r Source #

Eliminator for the existential carrier types of an Intertwiner.

downThenAcross :: forall {k1} (t :: k1 -> k1 -> k1) arr (ch :: k1) (ch' :: k1) (a :: k1) (b :: k1). Tensor t arr => Sq t arr ch ch' a b -> arr (t ch a) (t ch' b) Source #

Go down (carrier map) then across (target body).

A nondegenerate intertwiner witness: counter state quotiented by parity. The payload is Char so the carrier slot and payload slot are type-distinct; slot confusion is a type error. These examples exercise both parities and both reset branches. A paired perturbation doctest on acrossThenDown shows the equality can fail, so these agreement cases are not vacuous.

>>> let counter = (Body $ \(n, r) -> let n' = if r then 0 else n + 1 in (n', if odd n' then 'x' else 'y')) :: Body (,) Int (->) Bool Char
>>> let parity = (Body $ \(b, r) -> let b' = not r && not b in (b', if b' then 'x' else 'y')) :: Body (,) Bool (->) Bool Char
>>> let sq = Sq odd counter parity :: Sq (,) (->) Int Bool Bool Char
>>> downThenAcross sq (4, False)
(True,'x')
>>> downThenAcross sq (4, True)
(False,'y')
>>> downThenAcross sq (5, False)
(False,'y')

acrossThenDown :: forall {k1} (t :: k1 -> k1 -> k1) arr (ch :: k1) (ch' :: k1) (a :: k1) (b :: k1). Tensor t arr => Sq t arr ch ch' a b -> arr (t ch a) (t ch' b) Source #

Go across (source body) then down (carrier map).

Agreement cases for the same witness:

>>> let counter = (Body $ \(n, r) -> let n' = if r then 0 else n + 1 in (n', if odd n' then 'x' else 'y')) :: Body (,) Int (->) Bool Char
>>> let parity = (Body $ \(b, r) -> let b' = not r && not b in (b', if b' then 'x' else 'y')) :: Body (,) Bool (->) Bool Char
>>> let sq = Sq odd counter parity :: Sq (,) (->) Int Bool Bool Char
>>> acrossThenDown sq (4, False)
(True,'x')
>>> acrossThenDown sq (4, True)
(False,'y')
>>> acrossThenDown sq (5, False)
(False,'y')

Perturbation: observe even-ness instead of odd-ness. The two paths now disagree, which proves the agreement cases above are not vacuous.

>>> let badCounter = (Body $ \(n, r) -> let n' = if r then 0 else n + 1 in (n', if even n' then 'x' else 'y')) :: Body (,) Int (->) Bool Char
>>> let bad = Sq odd badCounter parity :: Sq (,) (->) Int Bool Bool Char
>>> downThenAcross bad (4, False)
(True,'x')
>>> acrossThenDown bad (4, False)
(True,'y')

cascade :: forall {k2} (t :: k2 -> k2 -> k2) (arr :: k2 -> k2 -> Type) (b :: k2) (c :: k2) (a :: k2). Strength t arr => Circ t arr b c -> Circ t arr a b -> Circ t arr a c Source #

Carrier-tensoring composition of loose 1-cells.

The composite has carrier t ch ch' when the first body has carrier ch and the second has carrier ch'.

unitorLeft :: forall {k1} (t :: k1 -> k1 -> k1) (arr :: k1 -> k1 -> Type) (ch :: k1) (a :: k1) (b :: k1). (Unital t arr, Strength t arr) => Body t ch arr a b -> Intertwiner t arr a b Source #

Left unitor witness: composing a body with the identity at the unit carrier is isomorphic to the original body.

unitorRight :: forall {k1} (t :: k1 -> k1 -> k1) (arr :: k1 -> k1 -> Type) (ch :: k1) (a :: k1) (b :: k1). (Unital t arr, Strength t arr) => Body t ch arr a b -> Intertwiner t arr a b Source #

Right unitor witness.

unitorLeftSq :: forall {k} (t :: k -> k -> k) (arr :: k -> k -> Type) (ch :: k) (a :: k) (b :: k). (Unital t arr, Strength t arr) => Body t ch arr a b -> Sq t arr (t (Unit t) ch) ch a b Source #

Indexed left unitor square.

unitorRightSq :: forall {k} (t :: k -> k -> k) (arr :: k -> k -> Type) (ch :: k) (a :: k) (b :: k). (Unital t arr, Strength t arr) => Body t ch arr a b -> Sq t arr (t ch (Unit t)) ch a b Source #

Indexed right unitor square.

associator :: forall {k1} (t :: k1 -> k1 -> k1) (arr :: k1 -> k1 -> Type) (ch3 :: k1) (c :: k1) (d :: k1) (ch2 :: k1) (b :: k1) (ch1 :: k1) (a :: k1). Strength t arr => Body t ch3 arr c d -> Body t ch2 arr b c -> Body t ch1 arr a b -> Intertwiner t arr a d Source #

Associator witness: carrier bracketing of three composed bodies is isomorphic up to the associator of the tensor.

associatorSq :: forall {k1} (t :: k1 -> k1 -> k1) (arr :: k1 -> k1 -> Type) (ch3 :: k1) (c :: k1) (d :: k1) (ch2 :: k1) (b :: k1) (ch1 :: k1) (a :: k1). Strength t arr => Body t ch3 arr c d -> Body t ch2 arr b c -> Body t ch1 arr a b -> Sq t arr (t (t ch1 ch2) ch3) (t ch1 (t ch2 ch3)) a d Source #

Indexed associator square.

rightWhisker :: forall {k1} (t :: k1 -> k1 -> k1) (arr :: k1 -> k1 -> Type) (ch :: k1) (ch' :: k1) (a :: k1) (b :: k1) (d :: k1) (c :: k1). (Tensor t arr, Strength t arr) => Sq t arr ch ch' a b -> Body t d arr b c -> Sq t arr (t ch d) (t ch' d) a c Source #

Right whisker: tensor a square with an identity-on-boundaries 1-cell on the right.

leftWhisker :: forall {k1} (t :: k1 -> k1 -> k1) (arr :: k1 -> k1 -> Type) (d :: k1) (a' :: k1) (a :: k1) (ch :: k1) (ch' :: k1) (b :: k1). (Tensor t arr, Strength t arr) => Body t d arr a' a -> Sq t arr ch ch' a b -> Sq t arr (t d ch) (t d ch') a' b Source #

Left whisker: tensor an identity-on-boundaries 1-cell on the left of a square.

hcompose :: forall {k1} (t :: k1 -> k1 -> k1) (arr :: k1 -> k1 -> Type) (ch2 :: k1) (ch2' :: k1) (b :: k1) (c :: k1) (ch1 :: k1) (ch1' :: k1) (a :: k1). (Tensor t arr, Strength t arr) => Sq t arr ch2 ch2' b c -> Sq t arr ch1 ch1' a b -> Sq t arr (t ch1 ch2) (t ch1' ch2') a c Source #

Horizontal composition of two squares.

whiskerSq :: forall {k1} (t :: k1 -> k1 -> k1) arr (a' :: k1) (a :: k1) (b :: k1) (b' :: k1) (ch :: k1) (ch' :: k1). Tensor t arr => arr a' a -> arr b b' -> Sq t arr ch ch' a b -> Sq t arr ch ch' a' b' Source #

Boundary whisker: apply tight maps to the input and output boundaries of a square. This is the Sq side of the interchange law; the Poles side is iomap on the Moore-split representation.

Feedback on Circ

feedback :: forall {k2} (t :: k2 -> k2 -> k2) (arr :: k2 -> k2 -> Type) (s :: k2) (a :: k2) (b :: k2). Channel t arr => Circ t arr (t s a) (t s b) -> Circ t arr a b Source #

Close a feedback loop over a component s of the input/output object.

The 1-cell must be of the form Circ t arr (t s a) (t s b): the feedback value s appears as the first component of the tensor in both domain and codomain. The result moves s into the hidden carrier, turning it into state. This is the guarded / state-bootstrapping feedback of KSW, not the immediate fixed-point trace: yanking fails here, which is the expected behaviour for a feedback category.

Implemented by reassociating so that s becomes part of the carrier:

  feedback (Circ (Body f)) = Circ (Body (assoc .> f .> assoc'))

Polynomial interfaces

type System = SystemT (,) Source #

Cartesian systems: the state-pairing tensor is (,).

system :: forall arr s (p :: Poly). arr (s, Dir p) (s, Pos p) -> System arr s p Source #

Construct a cartesian System from its underlying arrow.

runSystem :: forall arr s (p :: Poly). System arr s p -> arr (s, Dir p) (s, Pos p) Source #

Inspect a cartesian System as its underlying arrow.

mooreSystem :: (s -> a -> s) -> (s -> b) -> System (->) s (Mono a b) Source #

Build a monomial System from a step and an observation.

This is the pointed-Moore view of a stateful morphism, expressed directly in System terminology. The state transition s -> a -> s and the observation s -> b are explicit; the seed is supplied later (for example by systemToProcess).

type Mono i o = 'Prod ('Const o) ('Exp i) Source #

The monomial interface: i directions (input), o positions (output).

data Morphism (p :: Poly) (q :: Poly) where Source #

A morphism p -> q in Poly, encoded as a natural transformation between the evaluated functors.

By the Yoneda / sigma universal property, this is equivalent to a bundle map: a function on positions together with a contravariant family of functions on directions.

Konst and Depend extend the original Poly sketch so that backward maps can depend on the current position, giving point-dependent lenses.

Constructors

Id :: forall (p :: Poly). Morphism p p

Identity morphism.

Point :: forall (q :: Poly). Eval q () -> Morphism 'Y q

Global element: a point of q as a morphism Y -> q.

By the Yoneda lemma, Poly(Y, q) ≅ q(1) ≅ Eval q ().

ConstMap :: forall a b. (a -> b) -> Morphism ('Const a) ('Const b)

Covariant embedding of a plain function into constants.

ExpMap :: forall a b. (a -> b) -> Morphism ('Exp b) ('Exp a)

Contravariant embedding of a plain function into exponentials.

Compose :: forall (q1 :: Poly) (q :: Poly) (p :: Poly). Morphism q1 q -> Morphism p q1 -> Morphism p q

Sequential composition.

Par :: forall (p1 :: Poly) (p' :: Poly) (q1 :: Poly) (q' :: Poly). Morphism p1 p' -> Morphism q1 q' -> Morphism ('Prod p1 q1) ('Prod p' q')

Parallel composition (cartesian product of morphisms).

Inl :: forall (p :: Poly) (q1 :: Poly). Morphism p ('Sum p q1)

Coproduct injections.

Inr :: forall (p :: Poly) (p1 :: Poly). Morphism p ('Sum p1 p) 
Case :: forall (p1 :: Poly) (q :: Poly) (q1 :: Poly). Morphism p1 q -> Morphism q1 q -> Morphism ('Sum p1 q1) q

Coproduct case analysis.

Fst :: forall (q :: Poly) (q1 :: Poly). Morphism ('Prod q q1) q

Product projections.

Snd :: forall (p1 :: Poly) (q :: Poly). Morphism ('Prod p1 q) q 
Pair :: forall (p :: Poly) (p1 :: Poly) (q1 :: Poly). Morphism p p1 -> Morphism p q1 -> Morphism p ('Prod p1 q1)

Product pairing.

Konst :: forall b (p :: Poly). b -> Morphism p ('Const b)

Global element (constant introduction).

Depend :: forall a (p1 :: Poly) (q :: Poly). (a -> Morphism p1 q) -> Morphism ('Prod ('Const a) p1) q

Copower universal property: a Const a-indexed family of morphisms.

TensorAssocL :: forall (p1 :: Poly) (q1 :: Poly) (r :: Poly). Morphism ('Tensor ('Tensor p1 q1) r) ('Tensor p1 ('Tensor q1 r))

Left associator for the Dirichlet tensor: ((p ⊗ q) ⊗ r) -> (p ⊗ (q ⊗ r)).

TensorAssocR :: forall (p1 :: Poly) (q1 :: Poly) (r :: Poly). Morphism ('Tensor p1 ('Tensor q1 r)) ('Tensor ('Tensor p1 q1) r)

Right associator for the Dirichlet tensor.

TensorBraid :: forall (p1 :: Poly) (q1 :: Poly). Morphism ('Tensor p1 q1) ('Tensor q1 p1)

Symmetry/braiding for the Dirichlet tensor: p ⊗ q -> q ⊗ p.

ParT :: forall da a db b dc c dd d. Morphism (Mono da a) (Mono db b) -> Morphism (Mono dc c) (Mono dd d) -> Morphism ('Tensor (Mono da a) (Mono dc c)) ('Tensor (Mono db b) (Mono dd d))

Functorial action of the Dirichlet tensor on monomial morphisms: f ⊗ g : (a·y^{da}) ⊗ (c·y^{dc}) -> (b·y^{db}) ⊗ (d·y^{dd}).

Restricted to monomials because the current Dir family cannot express position-dependent direction sets (in particular, Sum has no Dir row).

CompUnitL :: forall (q :: Poly). Netlist q => Morphism ('Comp 'Y q) q

Left unitor for the composition product: Y ◁ p ≅ p.

CompUnitL' :: forall (p :: Poly). Netlist p => Morphism p ('Comp 'Y p)

Inverse left unitor for the composition product.

CompUnitR :: forall (q :: Poly). Netlist q => Morphism ('Comp q 'Y) q

Right unitor for the composition product: p ◁ Y ≅ p.

CompUnitR' :: forall (p :: Poly). Netlist p => Morphism p ('Comp p 'Y)

Inverse right unitor for the composition product.

CompAssocL :: forall (p1 :: Poly) (q1 :: Poly) (r :: Poly). Morphism ('Comp ('Comp p1 q1) r) ('Comp p1 ('Comp q1 r))

Left associator for the composition product: ((p ◁ q) ◁ r) -> (p ◁ (q ◁ r)).

CompAssocR :: forall (p1 :: Poly) (q1 :: Poly) (r :: Poly). Morphism ('Comp p1 ('Comp q1 r)) ('Comp ('Comp p1 q1) r)

Right associator for the composition product.

CompT :: forall da a db b dc c dd d. Morphism (Mono da a) (Mono db b) -> Morphism (Mono dc c) (Mono dd d) -> Morphism ('Comp (Mono da a) (Mono dc c)) ('Comp (Mono db b) (Mono dd d))

Functorial action of the composition product on monomial morphisms: f ◁ g : (a·y^{da}) ◁ (c·y^{dc}) -> (b·y^{db}) ◁ (d·y^{dd}).

Restricted to monomials for the same reason as ParT.

Prism :: forall s a. (s -> Either a s) -> (a -> s) -> Morphism ('Prod ('Const s) ('Exp s)) ('Sum (Mono a a) (Mono s s))

Prism: a co-lens that matches on a sum-like position.

Forward pass match :: s -> Either a s; backward pass on the matched branch is build :: a -> s. On the unmatched branch the backward pass is the identity. Directions are identified with positions, which is the natural reading for set-valued polynomials.

Instances

Instances details
Category Morphism Source # 
Instance details

Defined in Circuit.Poly

Methods

id :: forall (a :: Poly). Morphism a a Source #

(.) :: forall (b :: Poly) (c :: Poly) (a :: Poly). Morphism b c -> Morphism a b -> Morphism a c Source #

lens :: (a -> b) -> (a -> db -> da) -> Morphism (Mono da a) (Mono db b) Source #

The general point-dependent lens.

Forward pass get :: a -> b; backward pass put :: a -> db -> da depends on the current position.

>>> let l = lens show (\n d -> n + d) :: Morphism (Mono Int Int) (Mono Int String)
>>> let (v, put) = applyLens l 40 in (v, put 2)
("40",42)

applyLens :: Morphism (Mono da a) (Mono db b) -> a -> (b, db -> da) Source #

Apply a monomial morphism as a lens: (get, put).

prism :: (s -> Either a s) -> (a -> s) -> Morphism (Mono s s) ('Sum (Mono a a) (Mono s s)) Source #

Prism: match on a sum-like source, build from the focused branch.

>>> let p = prism (\case Left n -> Left n; Right s -> Right (Right s)) Left :: Morphism (Mono (Either Int String) (Either Int String)) ('Sum (Mono Int Int) (Mono (Either Int String) (Either Int String)))
>>> case runMorphism p (EP (EK (Left 7), EE id)) of ES (Left (EP (EK n, EE k))) -> (n, k 1)
(7,Left 1)

type family Pos (p :: Poly) where ... Source #

Position set of a polynomial.

For a value of p(x), 'Pos p' is the index type of positions.

Equations

Pos 'Y = () 
Pos ('Const a) = a 
Pos ('Exp a) = () 
Pos ('Sum p q) = Either (Pos p) (Pos q) 
Pos ('Prod p q) = (Pos p, Pos q) 
Pos ('Tensor p q) = (Pos p, Pos q) 
Pos ('Comp p q) = (Pos p, Dir p -> Pos q) 

type family Dir (p :: Poly) where ... Source #

Direction set of a polynomial.

For a value of p(x) at a given position, 'Dir p' is the domain of the function into x.

Sum gets a flat direction space Either (Dir p) (Dir q). This is an over-approximation: only the branch selected by the position is in-fibre. It is nonetheless the right shape for dynamics, where the input direction is supplied after the position is observed: a wrong-branch direction is simply off-fibre. The netlist view (Netlist) remains position-dependent and still does not admit a Sum instance.

For Comp, Dir ('Comp p q) = ('Dir p, 'Dir q) is the same flat approximation: the q-position (hence its honest pin set) depends on which p-direction was taken. Exact for Sum-free factors with uniform directions — the monomial fragment.

Equations

Dir 'Y = () 
Dir ('Const a) = Void 
Dir ('Exp a) = a 
Dir ('Sum p q) = Either (Dir p) (Dir q) 
Dir ('Prod p q) = Either (Dir p) (Dir q) 
Dir ('Tensor p q) = (Dir p, Dir q) 
Dir ('Comp p q) = (Dir p, Dir q) 

Stream transformer (first-input-seeded processes)

data Process a b where Source #

A stateful process from a to b.

The existential state type s is hidden; the observable interface is the triple inject step extract. Keeping the triple as the primitive (rather than fusing extract into the step) preserves the streaming-statistics invariant that the first output is extract (inject x), before any step.

Constructors

Process :: forall s a b. (a -> s) -> (s -> a -> s) -> (s -> b) -> Process a b 

Instances

Instances details
Copy (->) a => Copy Process a Source # 
Instance details

Defined in Circuit.Process

Methods

copy :: Process a (a, a) Source #

Merge (->) a => Merge Process a Source # 
Instance details

Defined in Circuit.Process

Methods

plus :: Process (a, a) a Source #

Category Process Source # 
Instance details

Defined in Circuit.Process

Methods

id :: Process a a Source #

(.) :: Process b c -> Process a b -> Process a c Source #

Shared (,) Process Source #

Cartesian shared fusion on processes.

The two processes share one feedback channel s. At each tick the schedule chooses which body advances; the gated body's input is discarded and it does not step. Each process is injected lazily on its first firing, so a body that is never scheduled consumes no inputs and produces no outputs.

Instance details

Defined in Circuit.Process

Methods

sharedBy :: Schedule s -> Process (s, a) (s, b) -> Process (s, c) (s, d) -> Process (s, (a, c)) (s, These b d) Source #

Discard Process (a :: Type) Source # 
Instance details

Defined in Circuit.Process

Methods

discard :: Process a () Source #

Zero (->) a => Zero Process (a :: Type) Source # 
Instance details

Defined in Circuit.Process

Methods

zero :: Process () a Source #

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 (,) 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 #

Strength Either Process Source # 
Instance details

Defined in Circuit.Process

Methods

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

Strength (,) Process Source # 
Instance details

Defined in Circuit.Process

Methods

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

Traced Either Process Source # 
Instance details

Defined in Circuit.Process

Methods

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

Traced (,) Process Source # 
Instance details

Defined in Circuit.Process

Methods

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

Action (,) Process Source # 
Instance details

Defined in Circuit.Process

Methods

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

Tensor (,) Process Source # 
Instance details

Defined in Circuit.Process

Methods

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

Unital (,) Process Source # 
Instance details

Defined in Circuit.Process

scan :: Process a b -> [a] -> [b] Source #

List specialization of scanStream.

fold :: Process a b -> [a] -> Maybe b Source #

List specialization of foldStream.

systemToProcess :: s -> (s -> b) -> System (->) s (Mono a b) -> Process a b Source #

Convert a monomial System, an explicit seed, and a state observation into a first-input-seeded Process.

The observation s -> b is applied to the current state to produce each output, including the first output from the seed. The step system is used only for state transitions.

markSystem :: (k -> Bool) -> (s -> b) -> System (->) s (Mono a b) -> System (->) (Either s s) (Mono (Boundary k a) (Maybe b)) Source #

Lift a monomial System and a state observation into a boundary system over Boundary tokens.

Payloads are stepped through the inner system. Marks satisfying the halt predicate freeze the system and produce Nothing thereafter; non-halt marks leave the state unchanged and emit the current output. The halted state remembers the final inner state.

The returned system carries state Either s s: Left is running, Right is halted. This is the core combinator behind mark-driven halt: the finite mark alphabet k carries control tokens, while payloads carry data.

delay :: s -> Process s s Source #

One-tick delay with an initial value.

Output is s0 on the first tick and the input from the previous tick thereafter. This is the primitive that makes register productive: the feedback wire is observable one tick late.

register :: s -> Process (a, s) (b, s) -> Process a b Source #

Cross-tick register feedback.

Given an initial feedback value s0 and a process Process (a, s) (b, s), close the s wire so that the s produced at one tick is fed back as input at the next tick. This is the productive, strict-accumulator-safe analogue of the cartesian trace: the delay is explicit in the wiring rather than implicit in a lazy knot.

Compare with the cartesian trace on Process, which ties a lazy knot and diverges for strict state; register keeps strict state cells sound by making the one-tick delay observable.

For bodies whose fixed-point is independent of the initial feedback value (e.g. affine/stateless feedback such as ewmaBody), the same wiring can be expressed by swapping the feedback wire into the active position, applying strength (delay s0), and tracing.

mealy :: ch -> (ch -> a -> (ch, Maybe b)) -> Process a (Maybe b) Source #

Build a Process from a Mealy-style step.

The output may depend on the current input. The channel internally stores the most recent output so that the Moore-style Process interface is preserved.

runMealy :: Process a (Maybe b) -> [a] -> [b] Source #

List specialization of runMealyStream.

Channel poles (bi-polar effectful/process API; still the right tool for

newtype Out (arr :: k -> k1 -> Type) (a :: k1) Source #

Out is the companion of the identity functor. Covariant in a (sits in the output position).

Constructors

Out 

Fields

  • emit :: forall (x :: k). In arr x -> arr x a

    Emit through the companion, supplying the other pole.

newtype In (arr :: k -> k1 -> Type) (a :: k) Source #

In is the conjoint of the identity functor. Contravariant in a (sits in the input position).

Constructors

In 

Fields

  • commit :: forall (x :: k1). Out arr x -> arr a x

    Commit through the conjoint, supplying the other pole.

data Poles (arr :: k -> k1 -> Type) (a :: k) (b :: k1) Source #

A matched pair of channel poles: one In and one Out.

This is the bi-polar communication contract. The conjoint (In) consumes payloads of type a; the companion (Out) produces payloads of type b. For symmetric channels such as queues a = b.

Together with prefixIn and suffixOut, Poles carries an enriched profunctor structure over the base category arr: prefixIn is the left action of arr on In poles, and suffixOut is the right action of arr on Out poles.

Constructors

Poles 

Fields

  • conjoint :: In arr a

    Write pole (producer), the conjoint.

  • companion :: Out arr b

    Read pole (consumer), the companion.

close :: forall {k} arr (a :: k). In arr a -> Out arr a -> arr a a Source #

Plug an In and an Out of the same payload type together.

close feeds the Out into the In pole, producing a morphism arr a a from the paired payload type.

Yanking: for the unit poles from open, close (conjoint p) (companion p) = id.

prefixIn :: forall {k} arr (a :: k) (b :: k). Category arr => arr a b -> In arr b -> In arr a Source #

Precompose an arr-morphism with an In pole.

Given f :: arr a b and an In pole at type b, produce an In pole at type a. Running the resulting pole first executes f and then commits through the original pole.

This is the left (contravariant) action of the base category on In poles. Specialised to unit poles it is the canonical way to build effectful write poles.

>>> let polesU = open :: Poles (->) () ()
>>> let inA = prefixIn (const ()) (conjoint polesU) :: In (->) Int
>>> commit inA (companion polesU) 42
()

suffixOut :: forall {k} arr (a :: k) (b :: k). Category arr => Out arr a -> arr a b -> Out arr b Source #

Postcompose an arr-morphism with an Out pole.

Given an Out pole at type a and g :: arr a b, produce an Out pole at type b. Running the resulting pole first emits through the original pole and then executes g on the emitted value.

This is the right (covariant) action of the base category on Out poles. Specialised to unit poles it is the canonical way to build effectful read poles.

>>> let polesU = open :: Poles (->) () ()
>>> let outA = suffixOut (companion polesU) (const 42) :: Out (->) Int
>>> emit outA (conjoint polesU) ()
42

poles :: forall {k} arr (a :: k) (b :: k) (bot :: k). HasDual bot arr => arr a bot -> arr bot b -> Poles arr a b Source #

Build a Poles from a write morphism and a read morphism.

write :: arr a bot consumes the input payload and produces the dualising object; read :: arr bot b consumes the dualising object and produces the output payload. The dualising-object poles wire the two halves together.

This is the canonical way to turn a pair of primitive channel actions into a matched pair of In and Out poles.

Compositional spelling:

poles write receive =
  Poles (prefixIn write (conjoint open)) (suffixOut (companion open) receive)

polesK :: Monad m => (a -> m ()) -> m b -> Poles (K m) a b Source #

Specialization of poles for K actions.

write :: a -> m () consumes the input payload; receive :: m b produces the output payload. The dualising-object handling is hidden inside the K wrappers.

splay :: forall {k} arr (a :: k) (b :: k) (bot :: k). HasDual bot arr => Poles arr a b -> (arr a bot, arr bot b) Source #

Extract the primitive write and read actions from a Poles by plugging each pole with the dualising-object poles.

For a Poles built with poles, this recovers the original write :: arr a bot and receive :: arr bot b.

>>> let p = poles0 (\() -> ()) (const (42 :: Int)) :: Poles (->) () Int
>>> let (write, receive) = splay0 p
>>> (write (), receive ())
((),42)

(>:>) :: forall {k} (arr :: k -> k -> Type) (a :: k) (b :: k) (c :: k) (bot :: k). HasDual bot arr => Poles arr a b -> Poles arr b c -> Poles arr a c infixr 1 Source #

Forward-composition operator for Poles. p1 >:> p2 = compose p1 p2.

class Category arr => HasDual (bot :: k) (arr :: k -> k -> Type) where Source #

Arrows that have channel poles for a given dualising object bot.

The dualising object is the target of the polar pairing and the object through which the two poles of a Poles are plugged together. In the cartesian case it is the monoidal unit (); for halt-mark / delivery pairings it can be Bool.

The poles are the identity-on-bot morphism split into its two polar halves. The companion is constant; the conjoint delegates to the opposing companion.

These poles require the base arrow to support constant morphisms, so they are captured by this class rather than being definable for all arrows.

Methods

open :: Poles arr bot bot Source #

The dualising object as channel poles.

Yank

>>> let poles = open :: Poles (->) () ()
>>> close (conjoint poles) (companion poles) ()
()

Plug

>>> let polesA = open :: Poles (->) () ()
>>> let polesU = open :: Poles (->) () ()
>>> commit (conjoint polesA) (companion polesU) ()
()
>>> emit (companion polesA) (conjoint polesU) ()
()

Instances

Instances details
Monad m => HasDual () (K m :: Type -> Type -> Type) Source #

Dualising object () for K m.

Same shape as the (->) instance, but the constant companion returns () in the monad.

Instance details

Defined in Circuit.Poles

Methods

open :: Poles (K m) () () Source #

HasDual () (->) Source #

Dualising object () for (->).

The companion is the constant function returning (); the conjoint recursively emits through the supplied companion.

Instance details

Defined in Circuit.Poles

Methods

open :: Poles (->) () () Source #

Monad m => HasDual Bool (K m :: Type -> Type -> Type) Source #

Dualising object Bool for K m.

Same shape as the (->) instance, but the constant companion returns False in the monad.

Instance details

Defined in Circuit.Poles

Methods

open :: Poles (K m) Bool Bool Source #

HasDual Bool (->) Source #

Dualising object Bool for (->).

The companion is the constant function returning False; the conjoint recursively emits through the supplied companion. Because Bool is not terminal, copycat at Bool is the constant function, not the identity.

Instance details

Defined in Circuit.Poles

Methods

open :: Poles (->) Bool Bool Source #

(Monad m, Pointed s) => HasDual Void (Body Either s (K m) :: Type -> Type -> Type) Source #

Unit poles for Body Either s (K m) at Void.

Instance details

Defined in Circuit.Body

Methods

open :: Poles (Body Either s (K m)) Void Void Source #

Pointed s => HasDual Void (Body Either s (->) :: Type -> Type -> Type) Source #

Unit poles for Body Either s (->) at the unit object Void.

The coproduct case needs a distinguished element of the carrier s: on a Right x input the companion must return Left s for some s, and there is no ambient state to use. Pointed captures exactly that, which is weaker than Monoid. This is the structural pointedness requirement that makes Either differ from (,).

Instance details

Defined in Circuit.Body

Methods

open :: Poles (Body Either s (->)) Void Void Source #

Monad m => HasDual () (Body (,) s (K m) :: Type -> Type -> Type) Source #

Unit poles for Body (,) s (K m).

Same shape as the (->) instance, but the companion returns () in the monad and threads the ambient state through unchanged.

Instance details

Defined in Circuit.Body

Methods

open :: Poles (Body (,) s (K m)) () () Source #

HasDual () (Body (,) s (->) :: Type -> Type -> Type) Source #

Unit poles for Body (,) s (->) at the unit object ().

The companion discards its input and returns (); the conjoint delegates to the companion. Yanking recovers the identity on ().

Instance details

Defined in Circuit.Body

Methods

open :: Poles (Body (,) s (->)) () () Source #

Copycat / multiplicative excluded middle

copycat :: forall {k} (arr :: k -> k -> Type) (bot :: k). HasDual bot arr => Poles arr bot bot Source #

The copycat strategy at the dualising object bot.

This is the multiplicative excluded middle bot ⅋ bot⊥ for arrows that have poles at bot: a self-dual channel whose close is the identity on bot. It routes between the two poles without ever deciding which one holds.

The additive excluded middle bot ⊕ bot⊥ — a verdict, now — is not supported; there is no decide :: Either bot bot here, because only the routing witness is provable.

Boxes

box :: forall {k} (bot :: k) arr (a :: k) (b :: k). HasDual bot arr => Poles arr a b -> arr a b Source #

Close a Poles to a plain base-arrow morphism.

A matched pair of free poles (Poles) is a box with one input wire and one output wire. This helper embeds that box into a traced monoidal category by unit-plugging the remaining two slots, giving a plain arr a b: input on the left, output on the right, with the unit plumbing hidden.

>>> let p = poles0 (const ()) (const 42) :: Poles (->) () Int
>>> box @() p ()
42

boxAsymmetric :: forall {k} (bot :: k) (t :: k -> k -> k) arr (a :: k) (b :: k). (HasDual bot arr, Tensor t arr) => Poles arr a b -> arr (t a bot) (t bot b) Source #

Asymmetric box with the dualising object exposed on opposite sides.

Uses tensor at the base arrow level. The input carries the dualising object on the right and the output carries it on the left; most users will prefer the dualising-object-normalised box.

>>> let p = poles0 (const ()) (const 42) :: Poles (->) () Int
>>> boxAsymmetric @() p ((), ())
((),42)

Free

data Free (arr :: k -> k -> Type) (a :: k) (b :: k) Source #

The free category over a base arrow.

The two constructors are Lift, which embeds a base arrow, and Compose, which sequences two free morphisms. The universal fold out of Free is run.

>>> run (Lift (+1) :: Free (->) Int Int) 5
6
>>> run (Compose (Lift (+1)) (Lift (*2)) :: Free (->) Int Int) 5
11

Instances

Instances details
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 #

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 #

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 #

Category arr => Category (Free arr :: k -> k -> Type) Source # 
Instance details

Defined in Circuit.Layer

Methods

id :: forall (a :: k). Free arr a a Source #

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

Layer (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) Source #

Layer instance for the free category.

Without object constraints, folding is just recursive application of the target category's composition.

Instance details

Defined in Circuit.Layer

Associated Types

type Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr' 
Instance details

Defined in Circuit.Layer

type Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr' = Category arr'
type Run (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr 
Instance details

Defined in Circuit.Layer

type Run (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr = Category arr
type Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr 
Instance details

Defined in Circuit.Layer

type Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr = ()

Methods

unit :: forall (arr :: Type -> Type -> Type). Category arr => arr :~> Free arr Source #

run :: (Run (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr, Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr, Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr) => Free arr a b -> arr a b Source #

bind :: forall arr' (arr :: Cat2) a b. (Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr', Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr) => (arr :~> arr') -> Free arr a b -> arr' a b Source #

type Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr Source # 
Instance details

Defined in Circuit.Layer

type Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr = ()
type Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr' Source # 
Instance details

Defined in Circuit.Layer

type Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr' = Category arr'
type Run (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr Source # 
Instance details

Defined in Circuit.Layer

type Run (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr = Category arr

freeze :: forall {k} arr (a :: k) (b :: k). Category arr => Free arr a b -> arr a b Source #

Freeze a Free category into its base arrow.

This is a synonym for run Free.

>>> freeze (Lift (+1) :: Free (->) Int Int) 5
6

Layer tower

class Layer (f :: Cat2 -> Cat2) where Source #

A free construction over a base arrow.

  • unit includes the generators.
  • run folds the free syntax back into the same base category.
  • bind folds the free syntax into any Law-abiding target.

Minimal complete definition

unit, bind

Associated Types

type Law (f :: Cat2 -> Cat2) (arr' :: Cat2) Source #

What the target category must satisfy to receive a bind fold. run only needs the base category's own structure.

type Run (f :: Cat2 -> Cat2) (arr :: Cat2) Source #

What the base category must satisfy to receive a run fold back into itself. Defaults to no extra constraints.

type Run (f :: Cat2 -> Cat2) (arr :: Cat2) = ()

type Bind (f :: Cat2 -> Cat2) (arr :: Cat2) Source #

Extra constraints the source category must satisfy for a bind fold. Defaults to no extra constraints.

type Bind (f :: Cat2 -> Cat2) (arr :: Cat2) = ()

Methods

unit :: forall (arr :: Type -> Type -> Type). Category arr => arr :~> f arr Source #

Include a base arrow as a single generator.

run :: (Run f arr, Law f arr, Bind f arr) => f arr a b -> arr a b Source #

Fold the free syntax into the same base category.

Defaults to bind id, so the single eliminator vocabulary is coherent wherever it type-checks. Instances may still override this with a direct implementation if the weaker constraints of Run do not already imply Law and Bind.

bind :: forall arr' (arr :: Cat2) a b. (Law f arr', Bind f arr) => (arr :~> arr') -> f arr a b -> arr' a b Source #

The universal fold out of the free construction into any Law-abiding target category.

Instances

Instances details
Layer (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) Source #

Layer instance for the free category.

Without object constraints, folding is just recursive application of the target category's composition.

Instance details

Defined in Circuit.Layer

Associated Types

type Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr' 
Instance details

Defined in Circuit.Layer

type Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr' = Category arr'
type Run (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr 
Instance details

Defined in Circuit.Layer

type Run (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr = Category arr
type Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr 
Instance details

Defined in Circuit.Layer

type Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr = ()

Methods

unit :: forall (arr :: Type -> Type -> Type). Category arr => arr :~> Free arr Source #

run :: (Run (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr, Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr, Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr) => Free arr a b -> arr a b Source #

bind :: forall arr' (arr :: Cat2) a b. (Law (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr', Bind (Free :: (Type -> Type -> Type) -> Type -> Type -> Type) arr) => (arr :~> arr') -> Free arr a b -> arr' a b Source #

Layer (Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type)))))))) Source #

Free symmetric monoidal category with a bimonoid.

Structural rows are interpreted in the target category: parallel composition uses tensor, braiding uses braid, and the bimonoid generators are the images under h of the source dictionaries carried by the SigCopy, SigDiscard, SigPlus, and SigZero constructors.

Conditional
bind h interprets bimonoid generators as images under h of the source arrow's dictionaries. This is the free-PROP fold only when h is a bimonoid homomorphism (automatic for the generator embedding, but must be verified for custom h).
Instance details

Defined in Circuit.Net

Methods

unit :: forall (arr :: Type -> Type -> Type). Category arr => arr :~> Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type))))))) arr Source #

run :: (Run (Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type)))))))) arr, Law (Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type)))))))) arr, Bind (Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type)))))))) arr) => Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type))))))) arr a b -> arr a b Source #

bind :: forall arr' (arr :: Cat2) a b. (Law (Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type)))))))) arr', Bind (Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type)))))))) arr) => (arr :~> arr') -> Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type))))))) arr a b -> arr' a b Source #

type Cat2 = Type -> Type -> Type Source #

The kind of Haskell categories: type-to-type hom-sets.

type (:~>) (arr :: k -> k1 -> Type) (arr' :: k -> k1 -> Type) = forall (x :: k) (y :: k1). arr x y -> arr' x y Source #

An arrow-to-arrow mapping (a natural transformation between profunctors).

lower :: forall (f :: Cat2 -> Cat2) (arr :: Type -> Type -> Type) (arr' :: Type -> Type -> Type). (Layer f, Category arr) => (f arr :~> arr') -> arr :~> arr' Source #

The left direction of the hom-set isomorphism: restrict a map out of the free layer to the generators.

Operators

(.>) :: forall {k} arr (a :: k) (b :: k) (c :: k). Category arr => arr a b -> arr b c -> arr a c Source #

Forward composition. f .> g = g . f

(|>) :: a -> (a -> b) -> b infixl 1 Source #

Forward application. x |> f = f x

(<|) :: (a -> b) -> a -> b infixr 0 Source #

Backward application. f <| x = f x

Bimonoid (structural rules)

class Copy (arr :: Type -> Type -> Type) a where Source #

Copy a value into a pair.

Laws:

  fst . copy = id              -- left unit
  snd . copy = id              -- right unit
  (copy × id) . copy = (id × copy) . copy  -- coassociativity
  braid . copy = copy            -- cocommutativity

Methods

copy :: arr a (a, a) Source #

Instances

Instances details
Copy FinRel () Source # 
Instance details

Defined in Circuit.FinRel

Methods

copy :: FinRel () ((), ()) Source #

Copy (->) a => Copy Process a Source # 
Instance details

Defined in Circuit.Process

Methods

copy :: Process a (a, a) Source #

Copy Pullback a Source #

Pullback-instance of the comonoid structure.

Copy's pullback is addition; discard's pullback is the zero cotangent. These are not used by the transposition step of reverse-mode AD (which encodes structural rows as Lifts to avoid channel-type constraints), but they make Pullback a full bimonoid carrier.

>>> runPullback (copy :: Pullback Int (Int, Int)) 3
(3,3)
>>> runPullback (discard :: Pullback Int ()) 5
()

NOTE: neither method here uses an Additive (->) a constraint — copying and discarding are linear as they stand. If the class head permits, drop the constraint; keeping a stray Additive reads as "addition happens in this instance", which is the confusion the paragraph above tries to dispel.

Instance details

Defined in Circuit.Pullback

Methods

copy :: Pullback a (a, a) Source #

KnownNat n => Copy FinRel (FinObj n) Source # 
Instance details

Defined in Circuit.FinRel

Methods

copy :: FinRel (FinObj n) (FinObj n, FinObj n) Source #

(Copy arr a, Merge arr a) => Copy (Dagger arr) a Source #

Forward copy, backward add — the bimonoid self-duality.

The interlock is the point to notice: Copy on the dagger requires Merge on the base. The comonoid and monoid cannot be granted separately in this construction; Dagger (FinRel k) is where that collapse becomes observable (see the circuits-axioma oracle).

Instance details

Defined in Circuit.Dagger

Methods

copy :: Dagger arr a (a, a) Source #

Copy (->) Integer Source # 
Instance details

Defined in Circuit.Bimonoid

Copy (->) () Source #

Unit trivially copies and discards.

>>> copy (() :: ())
((),())
>>> discard (() :: ())
()
Instance details

Defined in Circuit.Bimonoid

Methods

copy :: () -> ((), ()) Source #

Copy (->) Bool Source #

Booleans copy and discard.

>>> copy True
(True,True)
>>> discard True
()
Instance details

Defined in Circuit.Bimonoid

Methods

copy :: Bool -> (Bool, Bool) Source #

Copy (->) Double Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

copy :: Double -> (Double, Double) Source #

Copy (->) Float Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

copy :: Float -> (Float, Float) Source #

Copy (->) Int Source #

Numeric scalars copy and discard pointwise.

>>> copy (42 :: Int)
(42,42)
>>> discard (42 :: Int)
()
Instance details

Defined in Circuit.Bimonoid

Methods

copy :: Int -> (Int, Int) Source #

Copy (->) (Maybe a) Source #

Maybe copies and discards as a whole value.

Instance details

Defined in Circuit.Bimonoid

Methods

copy :: Maybe a -> (Maybe a, Maybe a) Source #

Copy (->) [a] Source #

Lists copy and discard as a whole value.

Instance details

Defined in Circuit.Bimonoid

Methods

copy :: [a] -> ([a], [a]) Source #

Copy (->) (a, b) Source #

Products copy and discard as a whole value.

Instance details

Defined in Circuit.Bimonoid

Methods

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

class Discard (arr :: k -> Type -> Type) (a :: k) where Source #

Discard a value.

Methods

discard :: arr a () Source #

Instances

Instances details
Discard FinRel () Source # 
Instance details

Defined in Circuit.FinRel

Methods

discard :: FinRel () () Source #

Discard Process (a :: Type) Source # 
Instance details

Defined in Circuit.Process

Methods

discard :: Process a () Source #

Discard Pullback (a :: Type) Source # 
Instance details

Defined in Circuit.Pullback

Methods

discard :: Pullback a () Source #

KnownNat n => Discard FinRel (FinObj n :: Type) Source # 
Instance details

Defined in Circuit.FinRel

Methods

discard :: FinRel (FinObj n) () Source #

(Discard arr a, Zero arr a) => Discard (Dagger arr :: Type -> Type -> Type) (a :: Type) Source # 
Instance details

Defined in Circuit.Dagger

Methods

discard :: Dagger arr a () Source #

Discard (->) Integer Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

discard :: Integer -> () Source #

Discard (->) () Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

discard :: () -> () Source #

Discard (->) Bool Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

discard :: Bool -> () Source #

Discard (->) Double Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

discard :: Double -> () Source #

Discard (->) Float Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

discard :: Float -> () Source #

Discard (->) Int Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

discard :: Int -> () Source #

Discard (->) (Maybe a :: Type) Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

discard :: Maybe a -> () Source #

Discard (->) ([a] :: Type) Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

discard :: [a] -> () Source #

Discard (->) ((a, b) :: Type) Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

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

class Merge (arr :: Type -> Type -> Type) a where Source #

Combine two values of the channel type.

Not the same as arithmetic +; this is the monoid operation by which parallel contributions to the same wire combine.

Methods

plus :: arr (a, a) a Source #

Instances

Instances details
Merge FinRel () Source # 
Instance details

Defined in Circuit.FinRel

Methods

plus :: FinRel ((), ()) () Source #

Merge (->) a => Merge Process a Source # 
Instance details

Defined in Circuit.Process

Methods

plus :: Process (a, a) a Source #

Merge (->) a => Merge Pullback a Source #

Pullback-instance of the additive/monoid structure.

Addition's pullback is copying; zero's pullback is discarding.

>>> runPullback (plus :: Pullback (Int, Int) Int) (1, 2)
3
>>> runPullback (zero :: Pullback () Int) ()
0
Instance details

Defined in Circuit.Pullback

Methods

plus :: Pullback (a, a) a Source #

KnownNat n => Merge FinRel (FinObj n) Source # 
Instance details

Defined in Circuit.FinRel

Methods

plus :: FinRel (FinObj n, FinObj n) (FinObj n) Source #

(Merge arr a, Copy arr a) => Merge (Dagger arr) a Source #

Forward add, backward copy.

Instance details

Defined in Circuit.Dagger

Methods

plus :: Dagger arr (a, a) a Source #

Merge (->) Integer Source # 
Instance details

Defined in Circuit.Bimonoid

Merge (->) () Source #

The unit type carries the trivial monoid.

>>> plus ((), ()) :: ()
()
>>> zero () :: ()
()
Instance details

Defined in Circuit.Bimonoid

Methods

plus :: ((), ()) -> () Source #

Merge (->) Bool Source #

Boolean monoid under disjunction.

Idempotent because True || True = True.

>>> plus (True, False) :: Bool
True
>>> zero () :: Bool
False
Instance details

Defined in Circuit.Bimonoid

Methods

plus :: (Bool, Bool) -> Bool Source #

Merge (->) Double Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

plus :: (Double, Double) -> Double Source #

Merge (->) Float Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

plus :: (Float, Float) -> Float Source #

Merge (->) Int Source #

Numeric carriers. plus is addition, zero is 0.

>>> plus (1, 2) :: Int
3
>>> zero () :: Int
0
>>> plus (1.0, 2.0) :: Double
3.0
>>> zero () :: Double
0.0
Instance details

Defined in Circuit.Bimonoid

Methods

plus :: (Int, Int) -> Int Source #

(Merge (->) a, Zero (->) a) => Merge (->) [a] Source #

Lists via elementwise plus, padded with zero.

For lists of unequal length, the shorter list is implicitly extended with the element zero. The unit is the empty list.

>>> plus ([1, 2], [3, 4, 5]) :: [Int]
[4,6,5]
>>> plus ([], [3, 4, 5]) :: [Int]
[3,4,5]
Instance details

Defined in Circuit.Bimonoid

Methods

plus :: ([a], [a]) -> [a] Source #

(Merge (->) a, Merge (->) b) => Merge (->) (a, b) Source #

Componentwise plus on pairs.

>>> plus ((3, 4), (5, 6)) :: (Int, Int)
(8,10)
Instance details

Defined in Circuit.Bimonoid

Methods

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

class Zero (arr :: Type -> k -> Type) (a :: k) where Source #

The neutral element for plus.

Methods

zero :: arr () a Source #

Instances

Instances details
Zero FinRel () Source # 
Instance details

Defined in Circuit.FinRel

Methods

zero :: FinRel () () Source #

Zero (->) a => Zero Process (a :: Type) Source # 
Instance details

Defined in Circuit.Process

Methods

zero :: Process () a Source #

Zero (->) a => Zero Pullback (a :: Type) Source # 
Instance details

Defined in Circuit.Pullback

Methods

zero :: Pullback () a Source #

KnownNat n => Zero FinRel (FinObj n :: Type) Source # 
Instance details

Defined in Circuit.FinRel

Methods

zero :: FinRel () (FinObj n) Source #

(Zero arr a, Discard arr a) => Zero (Dagger arr :: Type -> Type -> Type) (a :: Type) Source # 
Instance details

Defined in Circuit.Dagger

Methods

zero :: Dagger arr () a Source #

Zero (->) Integer Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

zero :: () -> Integer Source #

Zero (->) () Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

zero :: () -> () Source #

Zero (->) Bool Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

zero :: () -> Bool Source #

Zero (->) Double Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

zero :: () -> Double Source #

Zero (->) Float Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

zero :: () -> Float Source #

Zero (->) Int Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

zero :: () -> Int Source #

Zero (->) ([a] :: Type) Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

zero :: () -> [a] Source #

(Zero (->) a, Zero (->) b) => Zero (->) ((a, b) :: Type) Source # 
Instance details

Defined in Circuit.Bimonoid

Methods

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

type CopyDiscard (arr :: Type -> Type -> Type) a = (Copy arr a, Discard arr a) Source #

The bundled comonoid class, retained as a synonym.

type MergeZero (arr :: Type -> Type -> Type) a = (Merge arr a, Zero arr a) Source #

The bundled monoid class, retained as a synonym.

type Bimonoid (arr :: Type -> Type -> Type) a = (Copy arr a, Discard arr a, Merge arr a, Zero arr a) Source #

Both the comonoid and monoid on a channel object.

A constraint synonym — no instance required. On a cartesian base arrow, every type carries both structures. This is the precondition for mirror to be total on that base arrow.

Dagger (free dagger category)

data Dagger (arr :: k -> k -> Type) (a :: k) (b :: k) Source #

The free dagger category over a base arrow.

Dagger arr a b is a pair of arrows arr a b (forward) and arr b a (backward). Composition is covariant forward, contravariant backward: Dagger f g . Dagger f' g' = Dagger (f . f') (g' . g).

>>> let d = Dagger (+1) (subtract 1) :: Dagger (->) Int Int
>>> front d 5
6
>>> back d 6
5

Constructors

Dagger 

Fields

  • front :: arr a b

    The forward direction.

  • back :: arr b a

    The backward direction.

Instances

Instances details
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 #

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 #

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 #

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 #

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 #

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 #

(CopyT t arr a, MergeT t arr a) => CopyT (t :: k -> k -> k) (Dagger arr :: k -> k -> Type) (a :: k) Source #

Tensor-generic bimonoid interlock through Dagger.

These instances mirror the cartesian ones above, but work for any wiring tensor t. They are the missing lemma that makes mirror total: a Net over 'Dagger arr' can transpose its bimonoid rows because the dagger swaps the tensor-comonoid and tensor-monoid dictionaries.

>>> let d = copyT @(,) @(Dagger (->)) @Int :: Dagger (->) Int (Int, Int)
>>> front d 5
(5,5)
>>> back d (2, 3)
5
Instance details

Defined in Circuit.Dagger

Methods

copyT :: Dagger arr a (t a a) Source #

(DiscardT t arr a, ZeroT t arr a) => DiscardT (t :: k -> k -> k) (Dagger arr :: k -> k -> Type) (a :: k) Source # 
Instance details

Defined in Circuit.Dagger

Methods

discardT :: Dagger arr a (Unit t) Source #

(MergeT t arr a, CopyT t arr a) => MergeT (t :: k -> k -> k) (Dagger arr :: k -> k -> Type) (a :: k) Source # 
Instance details

Defined in Circuit.Dagger

Methods

plusT :: Dagger arr (t a a) a Source #

(ZeroT t arr a, DiscardT t arr a) => ZeroT (t :: k -> k -> k) (Dagger arr :: k -> k -> Type) (a :: k) Source # 
Instance details

Defined in Circuit.Dagger

Methods

zeroT :: Dagger arr (Unit t) a Source #

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

Defined in Circuit.Dagger

Methods

id :: forall (a :: k). Dagger arr a a Source #

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

(Discard arr a, Zero arr a) => Discard (Dagger arr :: Type -> Type -> Type) (a :: Type) Source # 
Instance details

Defined in Circuit.Dagger

Methods

discard :: Dagger arr a () Source #

(Zero arr a, Discard arr a) => Zero (Dagger arr :: Type -> Type -> Type) (a :: Type) Source # 
Instance details

Defined in Circuit.Dagger

Methods

zero :: Dagger arr () a Source #

(Copy arr a, Merge arr a) => Copy (Dagger arr) a Source #

Forward copy, backward add — the bimonoid self-duality.

The interlock is the point to notice: Copy on the dagger requires Merge on the base. The comonoid and monoid cannot be granted separately in this construction; Dagger (FinRel k) is where that collapse becomes observable (see the circuits-axioma oracle).

Instance details

Defined in Circuit.Dagger

Methods

copy :: Dagger arr a (a, a) Source #

(Merge arr a, Copy arr a) => Merge (Dagger arr) a Source #

Forward add, backward copy.

Instance details

Defined in Circuit.Dagger

Methods

plus :: Dagger arr (a, a) a Source #

transpose :: forall {k} (arr :: k -> k -> Type) (a :: k) (b :: k). Dagger arr a b -> Dagger arr b a Source #

The dagger operation: braid forward and backward.

Involutive: transpose . transpose = id.

SMC

type SMC (w :: Type -> Type -> Type) (arr :: Type -> Type -> Type) = Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type))) arr Source #

Free symmetric monoidal category over wiring tensor w.

Net

type Net (w :: Type -> Type -> Type) (arr :: Type -> Type -> Type) = Syntax ((SigCompose :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPar w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigSwap w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigCopy w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigDiscard w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: ((SigPlus w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type) :+: (SigZero w :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type))))))) arr Source #

The free symmetric monoidal category with a bimonoid.

Net is the free Syntax over the signature sum

SigCompose :+: SigPar w :+: SigSwap w :+: SigCopy w :+: SigDiscard w :+: SigPlus w :+: SigZero w

The Lift constructor embeds a base arrow; the Op constructor holds one of the signature nodes. Smart constructors lift and braid build the common cases, and widen embeds an entire SMC circuit.

melt :: forall (w :: Type -> Type -> Type) (t :: Type -> Type -> Type) (arr :: Type -> Type -> Type) a b. (Traced t arr, Action w arr) => Net w arr a b -> Trace t arr a b Source #

Melt the structural rows of a Net into the free Trace syntax.

The interpretation from the free symmetric monoidal category with bimonoid to the free traced monoidal category. Structural rows (SigPar, SigCopy, SigPlus, etc.) become opaque base-arrow operations wrapped in base; SigCompose uses the Category instance of Trace.

run Net = eval . melt@.

>>> eval (melt (lift (+1) :: Net (,) (->) Int Int) :: Trace (,) (->) Int Int) 5
6

Pullback (linear cotangent maps)

newtype Pullback b a Source #

A linear map from output cotangents to input cotangents, read as an arrow b -> a.

>>> let pb = Pullback (*2) :: Pullback Double Double
>>> runPullback pb 3
6.0

Constructors

Pullback 

Fields

  • runPullback :: b -> a

    Apply the pullback to an output cotangent.

Instances

Instances details
Copy Pullback a Source #

Pullback-instance of the comonoid structure.

Copy's pullback is addition; discard's pullback is the zero cotangent. These are not used by the transposition step of reverse-mode AD (which encodes structural rows as Lifts to avoid channel-type constraints), but they make Pullback a full bimonoid carrier.

>>> runPullback (copy :: Pullback Int (Int, Int)) 3
(3,3)
>>> runPullback (discard :: Pullback Int ()) 5
()

NOTE: neither method here uses an Additive (->) a constraint — copying and discarding are linear as they stand. If the class head permits, drop the constraint; keeping a stray Additive reads as "addition happens in this instance", which is the confusion the paragraph above tries to dispel.

Instance details

Defined in Circuit.Pullback

Methods

copy :: Pullback a (a, a) Source #

Merge (->) a => Merge Pullback a Source #

Pullback-instance of the additive/monoid structure.

Addition's pullback is copying; zero's pullback is discarding.

>>> runPullback (plus :: Pullback (Int, Int) Int) (1, 2)
3
>>> runPullback (zero :: Pullback () Int) ()
0
Instance details

Defined in Circuit.Pullback

Methods

plus :: Pullback (a, a) a Source #

Category Pullback Source # 
Instance details

Defined in Circuit.Pullback

Methods

id :: Pullback a a Source #

(.) :: Pullback b c -> Pullback a b -> Pullback a c Source #

Discard Pullback (a :: Type) Source # 
Instance details

Defined in Circuit.Pullback

Methods

discard :: Pullback a () Source #

Zero (->) a => Zero Pullback (a :: Type) Source # 
Instance details

Defined in Circuit.Pullback

Methods

zero :: Pullback () a 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 #

Strength (,) Pullback Source # 
Instance details

Defined in Circuit.Pullback

Methods

strength :: Pullback b c -> Pullback (a, b) (a, 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 #

Action (,) Pullback Source # 
Instance details

Defined in Circuit.Pullback

Methods

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

Tensor (,) Pullback Source # 
Instance details

Defined in Circuit.Pullback

Methods

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

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

evalPullback :: Net (,) Pullback b a -> b -> a Source #

Evaluate a pullback net at a single output cotangent.

This is the one-shot reverse pass: the net was built by transposing a smooth net, and applying it to a cotangent db yields the input cotangent da.

Hyper

type Hyper = HyperA (->) Source #

The function-category hyperfunction.

newtype HyperA (arr :: Type -> k -> Type) (a :: k) (b :: k) Source #

A hyperfunction from a to b over the base category arr.

Constructors

HyperA 

Fields

  • invoke :: arr (HyperA arr b a) b

    Feed a continuation into the hyperfunction.

Instances

Instances details
Category Hyper Source # 
Instance details

Defined in Circuit.Hyper

Methods

id :: Hyper a a Source #

(.) :: Hyper b c -> Hyper a b -> Hyper 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 #

Strength (,) Hyper Source # 
Instance details

Defined in Circuit.Hyper

Methods

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

Traced (,) Hyper Source # 
Instance details

Defined in Circuit.Hyper

Methods

trace :: Hyper (a, b) (a, c) -> Hyper b 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 #

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 #

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 #

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

Defined in Circuit.Hyper

Methods

id :: HyperA (K m) a a Source #

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

lift :: (a -> b) -> Hyper a b Source #

Embed a plain function into a hyperfunction.

>>> observe (lift (+1)) 5
6

observe :: Hyper a b -> a -> b Source #

Extract a plain function from a hyperfunction.

>>> observe (lift reverse) "hello"
"olleh"

push :: (a -> b) -> Hyper a b -> Hyper a b Source #

Push a plain function onto a hyperfunction.

>>> observe (push (+1) (lift (*2))) 5
6

runHyper :: Hyper a a -> a Source #

Close the self-referential loop.

>>> runHyper (Hyper $ \_ -> 42 :: Int)
42

liftK :: forall (m :: Type -> Type) a b. Monad m => K m a b -> HyperA (K m) a b Source #

Embed a Kleisli arrow into a hyperfunction.

observeK :: Monad m => HyperA (K m) a b -> a -> m b Source #

Extract the underlying Kleisli arrow from a hyperfunction.

pushK :: forall (m :: Type -> Type) a b. Monad m => K m a b -> HyperA (K m) a b -> HyperA (K m) a b Source #

Push a Kleisli arrow onto a hyperfunction.

runHyperK :: MonadFix m => HyperA (K m) a a -> m a Source #

Close the self-referential loop using mfix.

encode :: Trace (,) (->) a b -> Hyper a b Source #

Encode a function-category Trace into a Hyper.

This is the unique traced functor from the initial syntax (Trace) to the final object (Hyper), satisfying the commuting triangle observe . encode = eval.

base constructors embed directly via lift; yank constructors become trace over a hyperfunction.

>>> import qualified Circuit.Trace as Trace
>>> observe (encode (Trace.base (+1) :: Trace.Trace (,) (->) Int Int)) 5
6

encodeK :: forall (m :: Type -> Type) a b. MonadFix m => Trace (,) (K m) a b -> HyperA (K m) a b Source #

Encode a Kleisli Trace into a HyperA (K m).

encodeEither :: (Either a b -> Either a c) -> Hyper (Either a b -> c) (Either a b -> c) Source #

Encode an Either-loop as a self-referential Hyper.

Whereas encode handles the (,) tensor using Hyper's own Traced instance, this preserves the Either-loop state in the function domain. Left a feeds back; Right c terminates with output.

>>> :{
let step = \case
      Right n | n < 3 -> Left (n + 1)
      Right n         -> Right n
      Left n  | n < 3 -> Left (n + 1)
      Left n          -> Right n
:}
>>> runEither step (0 :: Int)
3

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

Run an encodeEither-encoded circuit from initial input b.

encodeEither embeds the Either state machine into Hyper, runHyper ties the self-referential knot, and Right b injects the initial state.

>>> :{
let step = \case
      Right n | n < 3 -> Left (n + 1)
      Right n         -> Right n
      Left n  | n < 3 -> Left (n + 1)
      Left n          -> Right n
:}
>>> runEither step (0 :: Int)
3

Tensor

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])

Stamped values

data Stamped r a Source #

A value a labelled by an occurrence token r.

Constructors

Stamped 

Fields

  • stamp :: r

    Occurrence token / receipt. Not touched by fmap.

  • stamped :: a

    The labelled payload.

Instances

Instances details
Bifunctor Stamped Source # 
Instance details

Defined in Circuit.Stamped

Methods

bimap :: (a -> b) -> (c -> d) -> Stamped a c -> Stamped b d #

first :: (a -> b) -> Stamped a c -> Stamped b c #

second :: (b -> c) -> Stamped a b -> Stamped a c #

Functor (Stamped r) Source # 
Instance details

Defined in Circuit.Stamped

Methods

fmap :: (a -> b) -> Stamped r a -> Stamped r b #

(<$) :: a -> Stamped r b -> Stamped r a #

Foldable (Stamped r) Source # 
Instance details

Defined in Circuit.Stamped

Methods

fold :: Monoid m => Stamped r m -> m #

foldMap :: Monoid m => (a -> m) -> Stamped r a -> m #

foldMap' :: Monoid m => (a -> m) -> Stamped r a -> m #

foldr :: (a -> b -> b) -> b -> Stamped r a -> b #

foldr' :: (a -> b -> b) -> b -> Stamped r a -> b #

foldl :: (b -> a -> b) -> b -> Stamped r a -> b #

foldl' :: (b -> a -> b) -> b -> Stamped r a -> b #

foldr1 :: (a -> a -> a) -> Stamped r a -> a #

foldl1 :: (a -> a -> a) -> Stamped r a -> a #

toList :: Stamped r a -> [a] #

null :: Stamped r a -> Bool #

length :: Stamped r a -> Int #

elem :: Eq a => a -> Stamped r a -> Bool #

maximum :: Ord a => Stamped r a -> a #

minimum :: Ord a => Stamped r a -> a #

sum :: Num a => Stamped r a -> a #

product :: Num a => Stamped r a -> a #

Traversable (Stamped r) Source # 
Instance details

Defined in Circuit.Stamped

Methods

traverse :: Applicative f => (a -> f b) -> Stamped r a -> f (Stamped r b) #

sequenceA :: Applicative f => Stamped r (f a) -> f (Stamped r a) #

mapM :: Monad m => (a -> m b) -> Stamped r a -> m (Stamped r b) #

sequence :: Monad m => Stamped r (m a) -> m (Stamped r a) #

(Eq r, Eq a) => Eq (Stamped r a) Source # 
Instance details

Defined in Circuit.Stamped

Methods

(==) :: Stamped r a -> Stamped r a -> Bool #

(/=) :: Stamped r a -> Stamped r a -> Bool #

(Show r, Show a) => Show (Stamped r a) Source # 
Instance details

Defined in Circuit.Stamped

Methods

showsPrec :: Int -> Stamped r a -> ShowS #

show :: Stamped r a -> String #

showList :: [Stamped r a] -> ShowS #

Additive poles

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 #

Par (multiplicative disjunction)

type family Bot (p :: k -> k -> k) :: k Source #

Unit of the tensor tensor ().

Instances

Instances details
type Bot Either Source #

The coproduct is the canonical tensor product on functions.

Instance details

Defined in Circuit.Par

type Bot Either = Void

class Category arr => Par (p :: k -> k -> k) (arr :: k -> k -> Type) where Source #

Multiplicative disjunction action on a category.

parP is the tensor product of morphisms. The unitors witness that ⊥ ⅋ a ≅ a and a ⅋ ⊥ ≅ a.

Methods

parP :: forall (a :: k) (b :: k) (c :: k) (d :: k). arr a b -> arr c d -> arr (p a c) (p b d) Source #

Parallel composition under tensor.

unitlP :: forall (a :: k). arr (p (Bot p) a) a Source #

Left unitor: ⊥ ⅋ a -> a.

unitlP' :: forall (a :: k). arr a (p (Bot p) a) Source #

Inverse left unitor: a -> ⊥ ⅋ a.

unitrP :: forall (a :: k). arr (p a (Bot p)) a Source #

Right unitor: a ⅋ ⊥ -> a.

unitrP' :: forall (a :: k). arr a (p a (Bot p)) Source #

Inverse right unitor: a -> a ⅋ ⊥.

Instances

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

Coproduct as multiplicative disjunction on K arrows.

Instance details

Defined in Circuit.Par

Methods

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

unitlP :: K m (Either (Bot Either) a) a Source #

unitlP' :: K m a (Either (Bot Either) a) Source #

unitrP :: K m (Either a (Bot Either)) a Source #

unitrP' :: K m a (Either a (Bot Either)) Source #

Par Either (->) Source #

Coproduct as multiplicative disjunction on functions.

The unit is the initial object Void; the unitors are the coproduct injections absorbed by the universal property.

Instance details

Defined in Circuit.Par

Methods

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

unitlP :: Either (Bot Either) a -> a Source #

unitlP' :: a -> Either (Bot Either) a Source #

unitrP :: Either a (Bot Either) -> a Source #

unitrP' :: a -> Either a (Bot Either) Source #

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

Left linear distributor: A ⊗ (B ⅋ C) -> (A ⊗ B) ⅋ C.

For (,) and Either this is the one-way product-over-coproduct map. Note that (_, Right c) = Right c discards the a; this is legal affinely but not in strict MLL. The distributors already live in the affine fragment.

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

Right linear distributor: (B ⅋ C) ⊗ A -> B ⅋ (C ⊗ A).

Mirror of distL: the same affine discard is present when the left summand is taken.

mix :: Void -> () Source #

Mix: the canonical map ⊥ -> 1 from tensor unit to tensor unit.

Every -value is vacuous, so it maps to the unique tensor unit.

Linear implication (internal hom)

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

Closed monoidal structure: A ⊸ B is the right adjoint of tensor.

Maps A ⊗ B -> C correspond to maps A -> B ⊸ C via curry/uncurry. eval is the counit A ⊗ (A ⊸ B) -> B (hom on the right of the tensor). That is the existing Chu convention; it differs from uncurry id by a braid. lolli is identity on the implication object, used to mention it.

Kind is fixed to Type so type applications stay concrete (GHC 9.14 panics on kind-polymorphic TypeApplications here).

Associated Types

type LolliT (t :: Type -> Type -> Type) (arr :: Type -> Type -> Type) a b Source #

The implication object A ⊸ B.

Indexed by the base arrow as well as the tensor, so (->) and Mat can both close (,) without colliding.

Methods

lolli :: arr a b -> arr (LolliT t arr a b) (LolliT t arr a b) Source #

Identity at the implication object. The argument is a type proxy.

eval :: arr (t a (LolliT t arr a b)) b Source #

Evaluation counit A ⊗ (A ⊸ B) -> B.

curry :: arr (t a b) c -> arr a (LolliT t arr b c) Source #

Curry the left factor: (A ⊗ B -> C) -> (A -> B ⊸ C).

uncurry :: arr a (LolliT t arr b c) -> arr (t a b) c Source #

Uncurry the left factor: (A -> B ⊸ C) -> (A ⊗ B -> C).

Instances

Instances details
Lolli (,) (->) Source #

Cartesian closed structure on functions: implication collapses to function space.

Instance details

Defined in Circuit.Linear

Associated Types

type LolliT (,) (->) a b 
Instance details

Defined in Circuit.Linear

type LolliT (,) (->) a b = a -> b

Methods

lolli :: (a -> b) -> LolliT (,) (->) a b -> LolliT (,) (->) a b Source #

eval :: (a, LolliT (,) (->) a b) -> b Source #

curry :: ((a, b) -> c) -> a -> LolliT (,) (->) b c Source #

uncurry :: (a -> LolliT (,) (->) b c) -> (a, b) -> c Source #

Exponentials

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

Exponential modality: object-level types for !A and ?A.

The structural rules are split into independent subclasses so that affine and linear uses of the modality differ only in their constraint sets, mirroring the Copy/Discard split at the base-arrow level.

  • !A has a contraction half (BangCopy) and a weakening half (BangWeaken). Linear logic requires both; affine logic requires only weakening.
  • ?A currently exposes only its unit rule (WhyNotIntro); the ⅋-monoid multiplication on ?A (WhyNotMerge) is missing. In the vocabulary of Dagger, ?A is currently CoAffine-only (the unit Zero) and the missing half is CoRelevant (the merge Merge).

Associated Types

type Bang (t :: k -> k -> k) (arr :: k -> k -> Type) a Source #

type WhyNot (t :: k -> k -> k) (arr :: k -> k -> Type) a = (result :: Type) | result -> a Source #

Instances

Instances details
Exponential (,) (->) Source #

Cartesian collapse: !A ≅ A, and ?A is the free monoid of lists.

Instance details

Defined in Circuit.Linear

Associated Types

type Bang (,) (->) a 
Instance details

Defined in Circuit.Linear

type Bang (,) (->) a = a
type WhyNot (,) (->) a 
Instance details

Defined in Circuit.Linear

type WhyNot (,) (->) a = [a]

class Exponential t arr => BangCopy (t :: Type -> Type -> Type) (arr :: Type -> Type -> Type) where Source #

Contraction half of !A: copy !A → !A ⊗ !A.

Methods

copyE :: arr (Bang t arr a) (t (Bang t arr a) (Bang t arr a)) Source #

Instances

Instances details
BangCopy (,) (->) Source # 
Instance details

Defined in Circuit.Linear

Methods

copyE :: Bang (,) (->) a -> (Bang (,) (->) a, Bang (,) (->) a) Source #

class Exponential t arr => BangWeaken (t :: Type -> Type -> Type) (arr :: Type -> Type -> Type) where Source #

Weakening half of !A: dereliction !A → A and discard !A → I.

Methods

discardE :: arr (Bang t arr a) (Unit t) Source #

derelict :: arr (Bang t arr a) a Source #

Instances

Instances details
BangWeaken (,) (->) Source # 
Instance details

Defined in Circuit.Linear

Methods

discardE :: Bang (,) (->) a -> Unit (,) Source #

derelict :: Bang (,) (->) a -> a Source #

class Exponential t arr => WhyNotIntro (t :: Type -> Type -> Type) (arr :: Type -> Type -> Type) where Source #

Unit rule for ?A: introduction A → ?A.

Methods

introduce :: arr a (WhyNot t arr a) Source #

Instances

Instances details
WhyNotIntro (,) (->) Source # 
Instance details

Defined in Circuit.Linear

Methods

introduce :: a -> WhyNot (,) (->) a Source #

class (Exponential t arr, Par p arr) => WhyNotMonoid (t :: Type -> Type -> Type) (p :: Type -> Type -> Type) (arr :: Type -> Type -> Type) where Source #

The ⅋-monoid structure on ?A.

Dual to the !-comonoid (BangCopy / BangWeaken), but living on the tensor product rather than the tensor product. mergeE is the multiplication ?A ⅋ ?A → ?A and zeroE is the unit ⊥ → ?A.

Methods

mergeE :: arr (p (WhyNot t arr a) (WhyNot t arr a)) (WhyNot t arr a) Source #

zeroE :: arr (Bot p) (WhyNot t arr a) Source #

Instances

Instances details
WhyNotMonoid (,) Either (->) Source # 
Instance details

Defined in Circuit.Linear

Methods

mergeE :: Either (WhyNot (,) (->) a) (WhyNot (,) (->) a) -> WhyNot (,) (->) a Source #

zeroE :: Bot Either -> WhyNot (,) (->) a Source #

type LinearBang (t :: Type -> Type -> Type) (arr :: Type -> Type -> Type) = (Exponential t arr, BangCopy t arr, BangWeaken t arr) Source #

Linear !A: both contraction and weakening.

type AffineBang (t :: Type -> Type -> Type) (arr :: Type -> Type -> Type) = (Exponential t arr, BangWeaken t arr) Source #

Affine !A: weakening only.

Channel product

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 #

Shared-medium fusion (the ⅋ connective)

data Pick Source #

A schedule decision: which poles advance on a shared channel.

  • L — advance the left body only; the right input is not consumed (corresponds to This).
  • R — advance the right body only; the left input is not consumed (corresponds to That).
  • Both b — advance both bodies, with the bias choosing the order (corresponds to These).

Constructors

L 
R 
Both Bias 

Instances

Instances details
Eq Pick Source # 
Instance details

Defined in Circuit.Shared

Methods

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

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

Show Pick Source # 
Instance details

Defined in Circuit.Shared

Methods

showsPrec :: Int -> Pick -> ShowS #

show :: Pick -> String #

showList :: [Pick] -> ShowS #

newtype Schedule s Source #

A schedule drives shared-medium fusion.

The state s is threaded through the fusion; in typical use it is the shared channel. At each step the schedule looks at the state and chooses which poles advance, returning the updated schedule state.

Constructors

Schedule 

Fields

  • chooseS :: s -> (s, Pick)

    Given the current shared state, return the updated state and a Pick value describing which poles advance and in what order.

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

Tensors that support shared-medium fusion of two knot bodies.

This is the operational content of the multiplicative disjunction: two sub-loops share one channel, and a Schedule resolves the interleaving. Contrast superpose, which keeps the channels independent (⊗).

Methods

sharedBy :: Schedule s -> arr (t s a) (t s b) -> arr (t s c) (t s d) -> arr (t s (t a c)) (t s (These b d)) Source #

Fuse two knot bodies over a shared channel.

The combined body has type arr (t s (t a c)) (t s (These b d)): one shared state s, paired inputs a and c, and a partial output. At each step the schedule chooses which body advances; the gated body's input is discarded and no output is produced for that side.

Instances

Instances details
Shared (,) Process Source #

Cartesian shared fusion on processes.

The two processes share one feedback channel s. At each tick the schedule chooses which body advances; the gated body's input is discarded and it does not step. Each process is injected lazily on its first firing, so a body that is never scheduled consumes no inputs and produces no outputs.

Instance details

Defined in Circuit.Process

Methods

sharedBy :: Schedule s -> Process (s, a) (s, b) -> Process (s, c) (s, d) -> Process (s, (a, c)) (s, These b d) Source #

Monad m => Shared (,) (K m) Source #

Cartesian shared fusion on K arrows.

Instance details

Defined in Circuit.Shared

Methods

sharedBy :: Schedule s -> K m (s, a) (s, b) -> K m (s, c) (s, d) -> K m (s, (a, c)) (s, These b d) Source #

Shared (,) (->) Source #

Cartesian shared fusion on functions.

The schedule chooses which bodies advance and in what order. L/R run only the chosen body and emit a partial This/That product; the other body's input is discarded. Both LeftFirst / Both RightFirst run both bodies, threading the shared state in the chosen order, and emit a total These product. When both bodies read and write s, the two orders are observationally different — this is the ⅋-vs-⊗ distinction.

Instance details

Defined in Circuit.Shared

Methods

sharedBy :: Schedule s -> ((s, a) -> (s, b)) -> ((s, c) -> (s, d)) -> (s, (a, c)) -> (s, These b d) Source #