module Meta.Invariant where
Meta: Invariantπ
An Invariant
functor is,
informally, one that has both a covariant and a contravariant dependency
on its argument type. For a motivating example, think of Dec
.
record Invariant (M : Effect) : TypeΟ where
private module M = Effect M
field
invmap: β {β} {ββ²} {A : Type β} {B : Type ββ²}
β (A β B) β (B β A) β M.β A β M.β B
open Invariant β¦ ... β¦ public
_<β>_
: β {β β'} {M : Effect} β¦ _ : Invariant M β¦ {A : Type β} {B : Type β'}
β A β B β M .Effect.β A β M .Effect.β B
_<β>_ f = invmap (Equiv.to f) (Equiv.from f)
We also provide versions of Idiom
and Alt
that only require an invariant
functor instead of a covariant one. A functor is Monoidal
if it commutes with products,
and Alternative
if it turns sums
into products.
record Monoidal (M : Effect) : TypeΟ where
private module M = Effect M
field
: Invariant M
β¦ Invariant-monoidal β¦ : M.β β€
munit _<,>_
: β {β} {ββ²} {A : Type β} {B : Type ββ²}
β M.β A β M.β B β M.β (A Γ B)
infixl 4 _<,>_
record Alternative (M : Effect) : TypeΟ where
private module M = Effect M
field
: Invariant M
β¦ Invariant-alternative β¦ : M.β β₯
empty _<+>_
: β {β} {ββ²} {A : Type β} {B : Type ββ²}
β M.β A β M.β B β M.β (A β B)
infixl 3 _<+>_
open Monoidal β¦ ... β¦ public
open Alternative β¦ ... β¦ public
We provide blanket instances mapping covariant classes to their invariant counterparts.
instance
: β {M : Effect} β β¦ Map M β¦ β Invariant M
Invariant-Map .Invariant.invmap f _ = f <$>_
Invariant-Map {-# OVERLAPPABLE Invariant-Map #-}
: β {M : Effect} β β¦ Idiom M β¦ β Monoidal M
Monoidal-Idiom .Monoidal.munit = pure tt
Monoidal-Idiom .Monoidal._<,>_ ma mb = _,_ <$> ma <*> mb
Monoidal-Idiom {-# OVERLAPPABLE Monoidal-Idiom #-}
: β {M : Effect} β β¦ Map M β¦ β β¦ Alt M β¦ β Alternative M
Alternative-Alt .Alternative.empty = fail
Alternative-Alt .Alternative._<+>_ ma mb = inl <$> ma <|> inr <$> mb
Alternative-Alt {-# INCOHERENT Alternative-Alt #-}