{-# LANGUAGE GADTs #-}

-- | Generic, untyped string-diagram syntax.
--
-- This is the surface that renderers consume.  It discards the Haskell
-- types but keeps the layout structure: boxes, wires, bends, swaps,
-- composition and tensor.  Constructors live here independently of any
-- particular semantic interpretation (polynomial lenses, matrices, etc.).
module Circuit.Diagram
  ( SDiagram (..),
    sCopy,
    sMerge,
    sDelete,
    sCreate,
  )
where

import Prelude

-- | Untyped drawing syntax for a string diagram.
--
-- This is what a renderer consumes.  It discards the Haskell types but
-- keeps the layout structure: boxes, wires, bends, swaps, composition and
-- tensor.
data SDiagram
  = -- | Straight identity wire.
    SWire
  | -- | Box with a label, a number of input ports and a number of output
    -- ports.
    SBox String Int Int
  | -- | Spider node with an input arity and an output arity (hypergraph
    -- junction: all its ports share one wire class).
    SSpider Int Int
  | -- | Prism box.
    SPrismBox
  | -- | Two diagrams side by side (tensor product).
    SBeside SDiagram SDiagram
  | -- | Two diagrams chained (composition).
    SThenD SDiagram SDiagram
  | -- | Cup (counit): bends two wires back to the unit.
    SBend
  | -- | Cap (unit): introduces two wires from the unit.
    SBend'
  | -- | Dual (rotate 180°).
    STurn SDiagram
  | -- | Left unitor @I ⊗ A -> A@.
    SUnitL
  | -- | Inverse left unitor @A -> I ⊗ A@.
    SUnitL'
  | -- | Right unitor @A ⊗ I -> A@.
    SUnitR
  | -- | Inverse right unitor @A -> A ⊗ I@.
    SUnitR'
  | -- | Associator @A ⊗ (B ⊗ C) -> (A ⊗ B) ⊗ C@.
    SAssoc
  | -- | Inverse associator @(A ⊗ B) ⊗ C -> A ⊗ (B ⊗ C)@.
    SAssoc'
  | -- | Symmetric braiding @A ⊗ B -> B ⊗ A@.
    SSwap
  | -- | Trace: hide the last input/output pair as a feedback loop.
    --
    -- A value @STrace d@ represents a diagram @d@ whose last input and last
    -- output are connected, removing one port from each boundary.
    STrace SDiagram
  deriving (SDiagram -> SDiagram -> Bool
(SDiagram -> SDiagram -> Bool)
-> (SDiagram -> SDiagram -> Bool) -> Eq SDiagram
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SDiagram -> SDiagram -> Bool
== :: SDiagram -> SDiagram -> Bool
$c/= :: SDiagram -> SDiagram -> Bool
/= :: SDiagram -> SDiagram -> Bool
Eq, Int -> SDiagram -> ShowS
[SDiagram] -> ShowS
SDiagram -> String
(Int -> SDiagram -> ShowS)
-> (SDiagram -> String) -> ([SDiagram] -> ShowS) -> Show SDiagram
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SDiagram -> ShowS
showsPrec :: Int -> SDiagram -> ShowS
$cshow :: SDiagram -> String
show :: SDiagram -> String
$cshowList :: [SDiagram] -> ShowS
showList :: [SDiagram] -> ShowS
Show)

-- | Copy spider: one input forked to two outputs.
sCopy :: SDiagram
sCopy :: SDiagram
sCopy = Int -> Int -> SDiagram
SSpider Int
1 Int
2

-- | Merge spider: two inputs joined to one output.
sMerge :: SDiagram
sMerge :: SDiagram
sMerge = Int -> Int -> SDiagram
SSpider Int
2 Int
1

-- | Delete spider: erases one input.
sDelete :: SDiagram
sDelete :: SDiagram
sDelete = Int -> Int -> SDiagram
SSpider Int
1 Int
0

-- | Create spider: produces one output from nothing.
sCreate :: SDiagram
sCreate :: SDiagram
sCreate = Int -> Int -> SDiagram
SSpider Int
0 Int
1