| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Proarrow.Tools.CCC
Description
A small HOAS (higher-order abstract syntax) front end for building morphisms in any
BiCCC, compiling through the free category of Proarrow.Category.Instance.Free with the
bicartesian closed structures rather than a bespoke one. A Free term tracks its free
variables via a context list, the way a well-scoped lambda calculus does; lam binds an
ordinary Haskell-level variable that Cast automatically "weakens" across nested lambdas so
inner lambdas can still refer to outer ones. toCCC interprets a closed term (no free
variables) into an actual morphism of the target category.
Synopsis
- toCCC :: forall {k} (a :: Syntax k) (b :: Syntax k). (BiCCC k, Ob a, Ob b) => Free ('[] :: [Syntax k]) (a ~~> b) -> Lower (Id :: k -> k -> Type) a ~> Lower (Id :: k -> k -> Type) b
- lam :: forall {k} (a :: Syntax k) (b :: Syntax k) (i :: Ctx k). (KnownCtx i, Ob a, Ob b) => ((forall (x :: Ctx k). Cast x (a ': i) => Free x a) -> Free (a ': i) b) -> Free i (a ~~> b)
- ($) :: forall {k} (a :: Syntax k) (b :: Syntax k) (i :: Ctx k). (Ob a, Ob b) => Free i (a ~~> b) -> Free i a -> Free i b
- lift :: forall {k} (a :: k) (b :: k) (i :: Ctx k). (Ob a, Ob b) => (a ~> b) -> Free i (F a :: FREE BiCCCStructs (Id :: k -> k -> Type)) -> Free i (F b :: FREE BiCCCStructs (Id :: k -> k -> Type))
- pattern (:&) :: (Ob a, Ob b) => Free i a -> Free i b -> Free i (a && b)
- either :: forall {k} (a :: Syntax k) (b :: Syntax k) (c :: Syntax k) (i :: Ctx k). (KnownCtx i, Ob a, Ob b, Ob c) => Free i (a ~~> c) -> Free i (b ~~> c) -> Free i (a || b) -> Free i c
- lft :: forall {k} (a :: Syntax k) (b :: Syntax k) (i :: Ctx k). (Ob a, Ob b) => Free i a -> Free i (a || b)
- rgt :: forall {k} (a :: Syntax k) (b :: Syntax k) (i :: Ctx k). (Ob a, Ob b) => Free i b -> Free i (a || b)
- data Free (i :: Ctx k) (a :: Syntax k)
- type Syntax k = FREE BiCCCStructs (Id :: k -> k -> Type)
- type Ctx k = [Syntax k]
- type family Mul (i :: Ctx k) :: Syntax k where ...
- class Cast (i :: Ctx k) (j :: Ctx k) where
- class KnownCtx (i :: Ctx k) where
- type BiCCCStructs = '[HasTerminalObject, HasInitialObject, HasBinaryProducts, HasBinaryCoproducts, Monoidal, Closed, Cartesian, Distributive]
- type F (a :: k) = 'EMB a :: FREE cs p
- injectRight :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => a ~> (b || a)
- swapProduct :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => (a && b) ~> (b && a)
- applyPair :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => ((a ~~> b) && a) ~> b
- curryPair :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => a ~> (b ~~> (a && b))
- flipCurried3 :: forall {k} (a :: k) (b :: k) (c :: k). (BiCCC k, Ob a, Ob b, Ob c) => (b ~~> (a ~~> (b ~~> c))) ~> (a ~~> (b ~~> c))
- swapSum :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => (a || b) ~> (b || a)
- caseEither :: forall {k} (a :: k) (b :: k) (c :: k). (BiCCC k, Ob a, Ob b, Ob c) => ((a || b) && ((a ~~> c) && (b ~~> c))) ~> c
Documentation
toCCC :: forall {k} (a :: Syntax k) (b :: Syntax k). (BiCCC k, Ob a, Ob b) => Free ('[] :: [Syntax k]) (a ~~> b) -> Lower (Id :: k -> k -> Type) a ~> Lower (Id :: k -> k -> Type) b Source Github #
Interpret a closed term (no free variables) into an actual morphism of the target
category: move the empty context from the terminal object to the monoidal unit, lower the
function-valued term (a closed one needs no arguments to uncurry), and fold into k with
generators interpreted by unwrapping Id (the free category was built over k's own
hom-sets directly).
lam :: forall {k} (a :: Syntax k) (b :: Syntax k) (i :: Ctx k). (KnownCtx i, Ob a, Ob b) => ((forall (x :: Ctx k). Cast x (a ': i) => Free x a) -> Free (a ': i) b) -> Free i (a ~~> b) Source Github #
($) :: forall {k} (a :: Syntax k) (b :: Syntax k) (i :: Ctx k). (Ob a, Ob b) => Free i (a ~~> b) -> Free i a -> Free i b infixr 0 Source Github #
Function application.
lift :: forall {k} (a :: k) (b :: k) (i :: Ctx k). (Ob a, Ob b) => (a ~> b) -> Free i (F a :: FREE BiCCCStructs (Id :: k -> k -> Type)) -> Free i (F b :: FREE BiCCCStructs (Id :: k -> k -> Type)) Source Github #
Embed a morphism of the target category as a term between embedded objects.
either :: forall {k} (a :: Syntax k) (b :: Syntax k) (c :: Syntax k) (i :: Ctx k). (KnownCtx i, Ob a, Ob b, Ob c) => Free i (a ~~> c) -> Free i (b ~~> c) -> Free i (a || b) -> Free i c Source Github #
lft :: forall {k} (a :: Syntax k) (b :: Syntax k) (i :: Ctx k). (Ob a, Ob b) => Free i a -> Free i (a || b) Source Github #
Inject as the left/right branch of a sum.
rgt :: forall {k} (a :: Syntax k) (b :: Syntax k) (i :: Ctx k). (Ob a, Ob b) => Free i b -> Free i (a || b) Source Github #
data Free (i :: Ctx k) (a :: Syntax k) Source Github #
A term with free variables i (innermost/most-recently-bound first) and result type
a: a morphism from the context product to a in the free BiCCC. A newtype
(rather than a bare type synonym) so that i is recoverable from a Free term's type: Mul
is many-to-one at the type-family level as far as GHC's injectivity checker is concerned (even
though it's mathematically injective here), which would otherwise leave i ambiguous wherever
it has to be inferred rather than given explicitly (e.g. picking which context a HOAS variable
reference in lam denotes).
type family Mul (i :: Ctx k) :: Syntax k where ... Source Github #
The context product: is the single object standing in for "all the bound
variables in Mul ii", a right fold with the most-recently-bound variable last. This mirrors
Proarrow.Category.Monoidal.Strictified's Fold, which puts its head leftmost. Fold itself
can't be reused, since curry/fst/snd expect the thing being abstracted over on the right
of the product.
class Cast (i :: Ctx k) (j :: Ctx k) where Source Github #
holds when context Cast i ji is context j with zero or more extra variables
pushed on top, letting a term built for j be used anywhere "deeper" than j.
type BiCCCStructs = '[HasTerminalObject, HasInitialObject, HasBinaryProducts, HasBinaryCoproducts, Monoidal, Closed, Cartesian, Distributive] Source Github #
The structures of a bicartesian closed category as a list for FREE: the five BiCCC
classes, the Cartesian marker supplying the formal tensor = product coercions (the free
category cannot state that type equality itself), and Distributive, for case analysis in the
presence of a context.
type F (a :: k) = 'EMB a :: FREE cs p Source Github #
A short alias for embedding a base-category object, so type applications built from it read
like the target signature: &&, || and ~~> on the free category are its object formers,
so (F a ~~> F b) && F a is the object it looks like.
injectRight :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => a ~> (b || a) Source Github #
Inject as the right element of a sum.
>>>import Prelude (Bool (..))>>>injectRight @Bool @Bool TrueRight True
swapProduct :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => (a && b) ~> (b && a) Source Github #
Swap a product.
>>>import Prelude (Bool (..))>>>swapProduct @Bool @Bool (True, False)(False,True)
applyPair :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => ((a ~~> b) && a) ~> b Source Github #
Apply a function to an argument, both bundled in a product.
>>>import Prelude (Bool (..), not)>>>applyPair @Bool @Bool (not, True)False
curryPair :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => a ~> (b ~~> (a && b)) Source Github #
Curry a pairing function.
>>>import Prelude (Bool (..))>>>curryPair @Bool @Bool True False(True,False)
flipCurried3 :: forall {k} (a :: k) (b :: k) (c :: k). (BiCCC k, Ob a, Ob b, Ob c) => (b ~~> (a ~~> (b ~~> c))) ~> (a ~~> (b ~~> c)) Source Github #
swapSum :: forall {k} (a :: k) (b :: k). (BiCCC k, Ob a, Ob b) => (a || b) ~> (b || a) Source Github #
Swap a sum, via either.
>>>import Prelude (Bool (..), Either (..))>>>swapSum @Bool @Bool (Left True)Right True>>>swapSum @Bool @Bool (Right False)Left False
caseEither :: forall {k} (a :: k) (b :: k) (c :: k). (BiCCC k, Ob a, Ob b, Ob c) => ((a || b) && ((a ~~> c) && (b ~~> c))) ~> c Source Github #
Eliminate a sum by applying whichever of the two functions matches the branch actually present.
>>>import Prelude (Bool (..), Either (..), not)>>>caseEither @Bool @Bool @Bool (Left True, (not, id))False>>>caseEither @Bool @Bool @Bool (Right True, (not, id))True