circuits
Safe HaskellNone
LanguageGHC2024

Circuit.Poly

Description

Polynomial objects are syntactic expressions, promoted to a kind:

p, q ::= Y the identity polynomial | Const A a constant set | Exp A y^A | Sum p q coproduct | Prod p q cartesian product | Tensor p q Dirichlet/parallel product | Comp p q composition (substitution)

The kind Poly is promoted, so polynomial expressions live at the type level. Eval is a GADT that witnesses the value shape of p(x). We use a GADT rather than a type family because Eval is not injective in x; the GADT lets GHC keep track of the evaluation variable without ambiguity.

Morphisms are natural transformations between the induced polynomial functors, equivalently bundle maps (positions forward, directions backward).

Two extra constructors make dependent lenses expressible:

  • Konst introduces a global element (a constant position).
  • Depend is the copower universal property: a Const a-indexed family of morphisms p -> q.

With them, the general point-dependent lens (get :: a -> b, put :: a -> db -> da) is a two-line Morphism.

The Tensor constructor adds the Dirichlet (parallel) product. It requires Pos and Dir type families because a value of (p ⊗ q)(x) is a pair of positions together with a single function out of the product of direction sets — not derivable from a pair of ordinary Eval values.

Worked examples: $netlist-view, $netlist-roundtrip, $dirichlet-tensor,

Synopsis

Polynomial expressions

data Poly Source #

Syntactic polynomial objects, promoted to a kind.

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 #

data Eval (p :: Poly) x where Source #

Values of a polynomial functor p evaluated at x.

The constructors mirror the polynomial grammar. EP and ES wrap the standard product and coproduct of Haskell ((,) and Either); they are not reimplemented, only tagged so that the polynomial shape remains inspectable.

ET is the Dirichlet tensor: a pair of positions with one function out of the product of direction sets. This cannot be built from a pair of ordinary Eval values, which is why Pos and Dir are needed.

EC is the composition product: a p-position with a q-component hung on each p-pin, and a path (dp, dq) into x.

Constructors

EY :: forall x. x -> Eval 'Y x 
EK :: forall c x. c -> Eval ('Const c) x 
EE :: forall a x. (a -> x) -> Eval ('Exp a) x 
ES :: forall (p1 :: Poly) x (q :: Poly). Either (Eval p1 x) (Eval q x) -> Eval ('Sum p1 q) x 
EP :: forall (p1 :: Poly) x (q :: Poly). (Eval p1 x, Eval q x) -> Eval ('Prod p1 q) x 
ET :: forall (p1 :: Poly) (q :: Poly) x. (Pos p1, Pos q) -> ((Dir p1, Dir q) -> x) -> Eval ('Tensor p1 q) x 
EC :: forall (p1 :: Poly) (q :: Poly) x. (Pos p1, Dir p1 -> Pos q) -> ((Dir p1, Dir q) -> x) -> Eval ('Comp p1 q) x 

Instances

Instances details
Functor (Eval p) Source # 
Instance details

Defined in Circuit.Poly

Methods

fmap :: (a -> b) -> Eval p a -> Eval p b #

(<$) :: a -> Eval p b -> Eval p a #

Positions and directions

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) 

Netlist view

class Netlist (p :: Poly) where Source #

Methods

toNet :: Eval p x -> (Pos p, Dir p -> x) Source #

Extract the position and pin assignment from a polynomial value.

fromNet :: Pos p -> (Dir p -> x) -> Eval p x Source #

Build a polynomial value from a position and pin assignment.

Instances

Instances details
Netlist 'Y Source # 
Instance details

Defined in Circuit.Poly

Methods

toNet :: Eval 'Y x -> (Pos 'Y, Dir 'Y -> x) Source #

fromNet :: Pos 'Y -> (Dir 'Y -> x) -> Eval 'Y x Source #

Netlist ('Const a) Source # 
Instance details

Defined in Circuit.Poly

Methods

toNet :: Eval ('Const a) x -> (Pos ('Const a), Dir ('Const a) -> x) Source #

fromNet :: Pos ('Const a) -> (Dir ('Const a) -> x) -> Eval ('Const a) x Source #

Netlist ('Exp a) Source # 
Instance details

Defined in Circuit.Poly

Methods

toNet :: Eval ('Exp a) x -> (Pos ('Exp a), Dir ('Exp a) -> x) Source #

fromNet :: Pos ('Exp a) -> (Dir ('Exp a) -> x) -> Eval ('Exp a) x Source #

Netlist ('Comp p q) Source # 
Instance details

Defined in Circuit.Poly

Methods

toNet :: Eval ('Comp p q) x -> (Pos ('Comp p q), Dir ('Comp p q) -> x) Source #

fromNet :: Pos ('Comp p q) -> (Dir ('Comp p q) -> x) -> Eval ('Comp p q) x Source #

(Netlist p, Netlist q) => Netlist ('Prod p q) Source # 
Instance details

Defined in Circuit.Poly

Methods

toNet :: Eval ('Prod p q) x -> (Pos ('Prod p q), Dir ('Prod p q) -> x) Source #

fromNet :: Pos ('Prod p q) -> (Dir ('Prod p q) -> x) -> Eval ('Prod p q) x Source #

Netlist ('Tensor p q) Source # 
Instance details

Defined in Circuit.Poly

Methods

toNet :: Eval ('Tensor p q) x -> (Pos ('Tensor p q), Dir ('Tensor p q) -> x) Source #

fromNet :: Pos ('Tensor p q) -> (Dir ('Tensor p q) -> x) -> Eval ('Tensor p q) x Source #

netRoundTrip :: forall (p :: Poly) x. Netlist p => Eval p x -> Eval p x Source #

Reassemble a value after taking it apart. This is the executable form of the round-trip law fromNet (toNet v) ≡ v.

tensorUnitorL :: forall (p :: Poly) x. Netlist p => Eval ('Tensor 'Y p) x -> Eval p x Source #

Left unitor for the Dirichlet tensor: Y ⊗ p ≅ p.

The Y factor is degenerate; collapse via fromNet on the other factor.

tensorUnitorL' :: forall (p :: Poly) x. Netlist p => Eval p x -> Eval ('Tensor 'Y p) x Source #

Inverse left unitor: p -> Y ⊗ p.

tensorUnitorR :: forall (p :: Poly) x. Netlist p => Eval ('Tensor p 'Y) x -> Eval p x Source #

Right unitor for the Dirichlet tensor: p ⊗ Y ≅ p.

tensorUnitorR' :: forall (p :: Poly) x. Netlist p => Eval p x -> Eval ('Tensor p 'Y) x Source #

Inverse right unitor: p -> p ⊗ Y.

Tensor functoriality

morphAt :: forall (p :: Poly) (p' :: Poly). (Netlist p, Netlist p') => Morphism p p' -> Pos p -> (Pos p', Dir p' -> Dir p) Source #

Read the bundle map off a Morphism at a chosen position.

Instantiating the output as Dir p turns an opaque morphism into a forward position plus a backward direction map — the crux that makes parT a few lines.

parT :: forall (p :: Poly) (q :: Poly) (p' :: Poly) (q' :: Poly) x. (Netlist p, Netlist q, Netlist p', Netlist q') => Morphism p p' -> Morphism q q' -> Eval ('Tensor p q) x -> Eval ('Tensor p' q') x Source #

Functorial action of the Dirichlet tensor on Netlist factors.

Map each tensor factor through its morphism independently; backward directions thread through both pullback maps.

Composition product

nestedToComp :: forall (p :: Poly) (q :: Poly) x. (Netlist p, Netlist q) => Eval p (Eval q x) -> Eval ('Comp p q) x Source #

Composition-product view of a nested evaluation Eval p (Eval q x).

Correctness iso (right): Eval (Comp p q) x ≅ Eval p (Eval q x).

compToNested :: forall (p :: Poly) (q :: Poly) x. (Netlist p, Netlist q) => Eval ('Comp p q) x -> Eval p (Eval q x) Source #

Nested evaluation from a composition-product value.

Correctness iso (left): inverse of nestedToComp.

compUnitorL :: forall (p :: Poly) x. Netlist p => Eval ('Comp 'Y p) x -> Eval p x Source #

Left unitor for the composition product: Y ◁ p -> p.

compUnitorL' :: forall (p :: Poly) x. Netlist p => Eval p x -> Eval ('Comp 'Y p) x Source #

Inverse left unitor for the composition product: p -> Y ◁ p.

compUnitorR :: forall (p :: Poly) x. Netlist p => Eval ('Comp p 'Y) x -> Eval p x Source #

Right unitor for the composition product: p ◁ Y -> p.

compUnitorR' :: forall (p :: Poly) x. Netlist p => Eval p x -> Eval ('Comp p 'Y) x Source #

Inverse right unitor for the composition product: p -> p ◁ Y.

compAssocL :: forall (p :: Poly) (q :: Poly) (r :: Poly) x. Eval ('Comp ('Comp p q) r) x -> Eval ('Comp p ('Comp q r)) x Source #

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

compAssocR :: forall (p :: Poly) (q :: Poly) (r :: Poly) x. Eval ('Comp p ('Comp q r)) x -> Eval ('Comp ('Comp p q) r) x Source #

Right associator for the composition product.

Tensor wiring

tensorEval :: forall (p :: Poly) (q :: Poly) a b. (Netlist p, Netlist q) => Eval p a -> Eval q b -> Eval ('Tensor p q) (a, b) Source #

Pair two polynomial values into a Dirichlet tensor (p ⊗ q).

Each factor contributes its position and pin assignment; the result is one joint assignment over the product of direction sets.

Morphisms

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 #

runMorphism :: forall (p :: Poly) (q :: Poly). Morphism p q -> forall x. Eval p x -> Eval q x Source #

Interpret a Morphism as a natural transformation.

Lenses

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

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

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)

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

The position-independent dagger case.

Expressible without Konst or Depend.

>>> let d = dagger (+1) (subtract 1) :: Morphism (Mono Int Int) (Mono Int Int)
>>> let (v, put) = applyLens d 5 in (v, put 6)
(6,5)

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

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

Prisms

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)

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

Extract the forward match of a prism.