module Meta.Invariant whereMeta: 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-monoidal β¦ : Invariant M
    munit : M.β β€
    _<,>_
      : β {β} {ββ²} {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-alternative β¦ : Invariant M
    empty : M.β β₯
    _<+>_
      : β {β} {ββ²} {A : Type β} {B : Type ββ²}
      β M.β A β M.β B β M.β (A β B)
  infixl 3 _<+>_
open Monoidal β¦ ... β¦ public
open Alternative β¦ ... β¦ publicWe provide blanket instances mapping covariant classes to their invariant counterparts.
instance
  Invariant-Map : β {M : Effect} β β¦ Map M β¦ β Invariant M
  Invariant-Map .Invariant.invmap f _ = f <$>_
  {-# OVERLAPPABLE Invariant-Map #-}
  Monoidal-Idiom : β {M : Effect} β β¦ Idiom M β¦ β Monoidal M
  Monoidal-Idiom .Monoidal.munit = pure tt
  Monoidal-Idiom .Monoidal._<,>_ ma mb = _,_ <$> ma <*> mb
  {-# OVERLAPPABLE Monoidal-Idiom #-}
  Alternative-Alt : β {M : Effect} β β¦ Map M β¦ β β¦ Alt M β¦ β Alternative M
  Alternative-Alt .Alternative.empty = fail
  Alternative-Alt .Alternative._<+>_ ma mb = inl <$> ma <|> inr <$> mb
  {-# INCOHERENT Alternative-Alt #-}