yaya-lens-0.0.1.0: src/Yaya/Lens.hs
{-# LANGUAGE Safe #-}
module Yaya.Lens
( AlgebraLens,
AlgebraLens',
BialgebraIso,
BialgebraIso',
CoalgebraPrism,
CoalgebraPrism',
anaIso,
birecursiveIso,
cataIso,
folded,
steppableIso,
unfolded,
)
where
import "base" Control.Category ((.))
import "base" Control.Monad ((<=<))
import "base" Data.Bifunctor (first)
import "base" Data.Function (const, flip, ($))
import "base" Data.Functor ((<$>))
import "base" Data.Traversable (Traversable, sequenceA)
import "lens" Control.Lens
( Iso,
Iso',
Lens,
Prism,
from,
iso,
lens,
matching,
prism,
review,
set,
view,
)
import "yaya" Yaya.Fold
( Corecursive,
Projectable,
Recursive,
Steppable,
ana,
cata,
embed,
project,
)
-- | An isomorphism between an @`Algebra` (->) f a@ and a @`Coalgebra` (->) g b@.
type BialgebraIso f g a b = Iso (f a) (g b) a b
type BialgebraIso' f a = BialgebraIso f f a a
type AlgebraLens f g a b = Lens (f a) (g b) a b
type AlgebraLens' f a = AlgebraLens f f a a
-- | A prism between an @`AlgebraM` (->) (`Either` (f a)) f a@ and a
-- @`Coalgebra` g b@.
type CoalgebraPrism f g a b = Prism (f a) (g b) a b
type CoalgebraPrism' f a = CoalgebraPrism f f a a
-- | The isomorphism between `embed` and `project`.
steppableIso ::
(Steppable (->) t f, Projectable (->) u g) => BialgebraIso f g t u
steppableIso = iso embed project
-- | The isomorphism between `cata` and `ana` as a function from an isomorphism
-- between (co)algebras to an isomorphism between the (co)recursive structure
-- and its folded value.
birecursiveIso ::
(Recursive (->) s f, Corecursive (->) t f) =>
BialgebraIso' f a ->
Iso s t a a
birecursiveIso φ = iso (cata (view φ)) (ana (review φ))
folded ::
( Recursive (->) s f,
Projectable (->) s f,
Corecursive (->) t f,
Traversable f
) =>
AlgebraLens' f a ->
Lens s t a a
folded φ =
lens (cata (view φ)) (\s -> ana . flip (set φ) $ cata (view φ) <$> project s)
-- | The prism between an unfold and a monadic fold.
unfolded ::
( Recursive (->) s f,
Projectable (->) s f,
Corecursive (->) t f,
Traversable f
) =>
CoalgebraPrism' f a ->
Prism s t a a
unfolded ψ =
prism
(ana $ review ψ)
(\s -> first (const $ ana project s) $ cata (matching ψ <=< sequenceA) s)
-- | Lift an isomorphism on natural transformations into an isomorphism on
-- `Recursive` structures.
--
-- source: Zanzi in [Monoidal Cafe #beginner-questions](https://discordapp.com/channels/1005220974523846678/1224686592187433082/1225431802068340796)
cataIso ::
( Recursive (->) t f,
Steppable (->) t f,
Recursive (->) u g,
Steppable (->) u g
) =>
(forall a. Iso' (f a) (g a)) ->
Iso' t u
cataIso nt = iso (cata $ embed . view nt) (cata $ embed . view (from nt))
-- | The dual of `cataIso`.
anaIso ::
( Corecursive (->) t f,
Projectable (->) t f,
Corecursive (->) u g,
Projectable (->) u g
) =>
(forall a. Iso' (f a) (g a)) ->
Iso' t u
anaIso nt = iso (ana $ view nt . project) (ana $ view (from nt) . project)