packages feed

circuits-0.2.0.0: src/Circuit.hs

-- | Circuit: free traced monoidal categories and hyperfunctions.
--
-- == 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
--
-- `Loop` is the inspectable GADT form. @Hyper@ is the final, coinductive
-- encoding. Convert a `Loop` to a @Hyper@ with `encode`, and observe it
-- with `observe` (or eliminate it with `runHyper`).
--
-- .> observe (encode (Circuit.Loop.Lift (+1) :: Loop (,) (->) Int Int)) 41
-- 42
--
-- == Overview
--
-- This library provides two representations of feedback:
--
-- * `Loop` (in "Circuit.Loop") — the initial, inspectable GADT encoding.
-- * @Hyper@ (in "Circuit.Hyper") — the final, coinductive encoding.
--
-- The `Traced` class (in "Circuit.Channel") abstracts the choice of tensor,
-- currently supporting lazy knots with @(,@) and iteration with `Either`.
--
-- All braided, cartesian, and cocartesian structure, plus the general
-- `ambientBy` state-threading combinator, lives in "Circuit.Tensor".
--
-- == Core Concepts
--
-- * __Tensor__ (@t@): The bifunctor pairing a feedback value with a payload
--   inside a `Loop` (currently @(,@) or `Either`).
--
-- * __Feedback value__: The component that travels around the loop (first
--   parameter of the tensor in a `Loop`).
--
-- * __Payload__: The value being transformed and emitted (second parameter
--   of the tensor).
--
-- * __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 `Loop`), @sift@ (`Net` to `Sym`),
--   @eval@ / @evalInto@ (@Syntax@ via an algebra).
--
-- * __Injections__ embed one construction into another without eliminating:
--   `unit` (base arrow into a `Layer`), `enrich` (`Loop` into `Net`),
--   @widen@ (`Sym` into `Net`), @algLoop@ / @algNet@ (direct GADT into @Syntax@).
--
-- * __Representation changes__: `encode` (`Loop` to @Hyper@),
--   `observe` / `runHyper` (@Hyper@ to function / fixed point).
module Circuit
  ( -- * Loop
    Loop (..),
    Traced,
    Strength,
    -- | Close a feedback loop. See "Circuit.Loop".
    trace,
    -- | Open a feedback loop. See "Circuit.Loop".
    strength,

    -- * Channel ends
    Out (..),
    In (..),
    Ends (..),
    close,
    prefixIn,
    suffixOut,
    ends,
    endsK,
    splay,
    HasUnit (..),

    -- * Boxes
    box,
    boxAsymmetric,

    -- * Queues
    Queue (..),
    openSTM,
    openIO,

    -- * Free
    Free,
    freeze,

    -- * Layer tower
    Layer (..),
    Cat2,
    (:~>),
    lower,

    -- * Discrete discharge kit
    compD,
    assocD,
    assocD',
    braidD,
    strengthD,
    traceD,

    -- * Operators
    (.>),
    (|>),
    (<|),

    -- * Dagger (bimonoid + dagger)
    CopyDiscard (..),
    MergeZero (..),
    Dagger (..),
    Bimonoid,
    transpose,

    -- * Sym
    Sym,

    -- * Net
    Net,
    enrich,
    melt,

    -- * Hyper
    Hyper (..),
    lift,
    observe,
    base,
    push,
    runHyper,
    encode,
    encodeEither,
    encodeFree,
    runEither,
    flatten,

    -- * Channel
    Braided (..),
    ambient,
    ambientBy,
    superpose,

    -- * Channel product
    Tensor (..),
    Action (..),
  )
where

import Circuit.Category (Ob, (.>), (<|), (|>))
import Circuit.Channel (Strength, Traced)
import Circuit.Channel qualified as Channel
import Circuit.Dagger
  ( Bimonoid,
    CopyDiscard (..),
    Dagger (..),
    MergeZero (..),
    transpose,
  )
import Circuit.Discrete
  ( assocD,
    assocD',
    braidD,
    compD,
    strengthD,
    traceD,
  )
import Circuit.Ends
  ( Ends (..),
    HasUnit (..),
    In (..),
    Out (..),
    Queue (..),
    box,
    boxAsymmetric,
    close,
    ends,
    endsK,
    openIO,
    openSTM,
    prefixIn,
    splay,
    suffixOut,
  )
import Circuit.Free
  ( Free (..),
    freeze,
  )
import Circuit.Hyper
  ( Hyper (..),
    base,
    encode,
    encodeEither,
    encodeFree,
    flatten,
    lift,
    observe,
    push,
    runEither,
    runHyper,
  )
import Circuit.Layer
  ( Cat2,
    Layer (..),
    lower,
    run,
    (:~>),
  )
import Circuit.Loop (Loop (..))
import Circuit.Loop qualified as Loop
import Circuit.Net
  ( Net,
    enrich,
    melt,
  )
import Circuit.Sym
import Circuit.Tensor
import Prelude

-- | Close a feedback loop. See "Circuit.Channel".
trace ::
  (Traced t arr, Ob arr a, Ob arr b, Ob arr c, Ob arr (t a b), Ob arr (t a c)) =>
  arr (t a b) (t a c) ->
  arr b c
trace = Channel.trace

-- | Open a feedback loop. See "Circuit.Channel".
strength ::
  (Strength t arr, Ob arr a, Ob arr b, Ob arr c, Ob arr (t a b), Ob arr (t a c)) =>
  arr b c ->
  arr (t a b) (t a c)
strength = Channel.strength