Evaluate a morphism as a function.

If the morphism will be evaluated only once (possibly with vectorized inputs), then direct evaluation will be much faster than compiling (via compile) and evaluating a standard Julia function.

Compare with functor.


Parse a wiring diagram from a Julia program.

For the most part, this is standard Julia code but we take a few liberties with the syntax. Products are represented as tuples. So if x and y are variables of type $X$ and $Y$, then (x,y) has type $X \otimes Y$. Also, both () and nothing are interpreted as the monoidal unit $I$.

Unlike in standard Julia, the call expressions f(x,y) and f((x,y)) are equivalent. Consequently, given morphisms $f: W \to X \otimes Y$ and $g: X \otimes Y \to Z$, the code

x, y = f(w)

is equivalent to g(f(w)). In standard Julia, at most one of these calls to g would be valid, unless g had multiple signatures.

The diagonals (copying and deleting) are implicit in the Julia syntax: copying is variable reuse and deleting is variable non-use. For the codiagonals (merging and creating), a special syntax is provided, reinterpreting Julia's vector literals. The merge of x1 and x2 is represented by the vector [x1,x2] and creation by the empty vector []. For example, f([x1,x2]) translates to compose(mmerge(X),f).

This macro is a wrapper around parse_wiring_diagram.


Construct an undirected wiring diagram using relation notation.

Unlike the @program macro for directed wiring diagrams, this macro departs from the usual semantics of the Julia programming language. Function calls with n arguments are now interpreted as assertions that an n-ary relation holds at a particular point. For example, the composition of binary relations R ⊆ X × Y and S ⊆ Y × Z can be represented as an undirected wiring diagram by the macro call

@relation (x,z) where (x::X, y::Y, z::Z) begin

In general, the context in the where clause defines the set of junctions in the diagram and variable sharing defines the wiring of ports to junctions.

The ports and junctions of the diagram may be typed or untyped, and the ports may be named or unnamed. Thus four possible types of diagrams may be returned, with the type determined by the form of relation header:

  1. Untyped, unnamed: @relation (x,z) where (x,y,z) ...
  2. Typed, unnamed: @relation (x,z) where (x::X, y::Y, z::Z) ...
  3. Untyped, named: @relation (out1=x, out2=z) where (x,y,z) ...
  4. Typed, named: @relation (out=1, out2=z) where (x::X, y::Y, z::Z) ...