{-# LANGUAGE Safe #-}

module Yaya.Unsafe.Zoo
  ( chrono,
    codyna,
    coelgot,
    cotraverse,
    dyna,
    elgot,
    fstream,
    futu,
    gpostpro,
    gprepro,
    stream,
    zygoHistoPrepro,
  )
where

import "base" Control.Applicative (Applicative (pure))
import "base" Control.Category (Category (id, (.)))
import "base" Control.Monad (Monad)
import "base" Data.Bifunctor (Bifunctor (second))
import "base" Data.Bitraversable (Bitraversable (bitraverse))
import "base" Data.Function (const, flip)
import "base" Data.Functor (Functor (fmap))
import "base" Data.Functor.Compose (Compose (Compose, getCompose))
import "base" Data.Functor.Identity (Identity (Identity, runIdentity))
import "base" Data.Traversable (Traversable)
import "comonad" Control.Comonad (Comonad)
import "comonad" Control.Comonad.Env (EnvT)
import "free" Control.Comonad.Cofree (Cofree)
import "free" Control.Monad.Trans.Free (Free)
import "yaya" Yaya.Fold
  ( Algebra,
    Coalgebra,
    Corecursive (ana),
    DistributiveLaw,
    ElgotAlgebra,
    ElgotCoalgebra,
    GAlgebra,
    GCoalgebra,
    Projectable (project),
    Recursive (cata),
    Steppable (embed),
    distEnvT,
    distIdentity,
    gana,
    seqIdentity,
  )
import "yaya" Yaya.Fold.Common (diagonal, fromEither)
import "yaya" Yaya.Fold.Native (distCofreeT)
import "yaya" Yaya.Pattern (Either, Maybe (Nothing), Pair ((:!:)), XNor (Both, Neither))
import qualified "this" Yaya.Unsafe.Fold as Unsafe
import qualified "this" Yaya.Unsafe.Fold.Instances as Unsafe -- FIXME: extremely unsafe

chrono ::
  (Functor f) =>
  GAlgebra (->) (Cofree f) f b ->
  GCoalgebra (->) (Free f) f a ->
  a ->
  b
chrono :: forall (f :: * -> *) b a.
Functor f =>
GAlgebra (->) (Cofree f) f b
-> GCoalgebra (->) (Free f) f a -> a -> b
chrono = DistributiveLaw (->) f (Cofree f)
-> DistributiveLaw (->) (FreeT f Identity) f
-> GAlgebra (->) (Cofree f) f b
-> GCoalgebra (->) (FreeT f Identity) f a
-> a
-> b
forall (w :: * -> *) (m :: * -> *) (f :: * -> *) b a.
(Comonad w, Monad m, Functor f) =>
DistributiveLaw (->) f w
-> DistributiveLaw (->) m f
-> GAlgebra (->) w f b
-> GCoalgebra (->) m f a
-> a
-> b
Unsafe.ghylo (DistributiveLaw (->) f f -> DistributiveLaw (->) f (Cofree f)
forall (f :: * -> *) (h :: * -> *).
(Functor f, Functor h) =>
DistributiveLaw (->) f h -> DistributiveLaw (->) f (Cofree h)
distCofreeT f (f a) -> f (f a)
forall a. a -> a
DistributiveLaw (->) f f
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id) (DistributiveLaw (->) f f
-> DistributiveLaw (->) (FreeT f Identity) f
forall (f :: * -> *) (h :: * -> *).
(Functor f, Functor h) =>
DistributiveLaw (->) h f -> DistributiveLaw (->) (Free h) f
Unsafe.seqFreeT f (f a) -> f (f a)
forall a. a -> a
DistributiveLaw (->) f f
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id)

codyna :: (Functor f) => Algebra (->) f b -> GCoalgebra (->) (Free f) f a -> a -> b
codyna :: forall (f :: * -> *) b a.
Functor f =>
Algebra (->) f b -> GCoalgebra (->) (Free f) f a -> a -> b
codyna Algebra (->) f b
φ = DistributiveLaw (->) f Identity
-> DistributiveLaw (->) (FreeT f Identity) f
-> GAlgebra (->) Identity f b
-> GCoalgebra (->) (FreeT f Identity) f a
-> a
-> b
forall (w :: * -> *) (m :: * -> *) (f :: * -> *) b a.
(Comonad w, Monad m, Functor f) =>
DistributiveLaw (->) f w
-> DistributiveLaw (->) m f
-> GAlgebra (->) w f b
-> GCoalgebra (->) m f a
-> a
-> b
Unsafe.ghylo f (Identity a) -> Identity (f a)
DistributiveLaw (->) f Identity
forall (f :: * -> *). Functor f => DistributiveLaw (->) f Identity
distIdentity (DistributiveLaw (->) f f
-> DistributiveLaw (->) (FreeT f Identity) f
forall (f :: * -> *) (h :: * -> *).
(Functor f, Functor h) =>
DistributiveLaw (->) h f -> DistributiveLaw (->) (Free h) f
Unsafe.seqFreeT f (f a) -> f (f a)
forall a. a -> a
DistributiveLaw (->) f f
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id) (Algebra (->) f b
φ Algebra (->) f b
-> (f (Identity b) -> f b) -> GAlgebra (->) Identity f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Identity b -> b) -> f (Identity b) -> f b
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Identity b -> b
forall a. Identity a -> a
runIdentity)

-- | [Recursion Schemes for Dynamic Programming](https://www.researchgate.net/publication/221440162_Recursion_Schemes_for_Dynamic_Programming)
dyna :: (Functor f) => GAlgebra (->) (Cofree f) f b -> Coalgebra (->) f a -> a -> b
dyna :: forall (f :: * -> *) b a.
Functor f =>
GAlgebra (->) (Cofree f) f b -> Coalgebra (->) f a -> a -> b
dyna GAlgebra (->) (Cofree f) f b
φ Coalgebra (->) f a
ψ = DistributiveLaw (->) f (Cofree f)
-> DistributiveLaw (->) Identity f
-> GAlgebra (->) (Cofree f) f b
-> GCoalgebra (->) Identity f a
-> a
-> b
forall (w :: * -> *) (m :: * -> *) (f :: * -> *) b a.
(Comonad w, Monad m, Functor f) =>
DistributiveLaw (->) f w
-> DistributiveLaw (->) m f
-> GAlgebra (->) w f b
-> GCoalgebra (->) m f a
-> a
-> b
Unsafe.ghylo (DistributiveLaw (->) f f -> DistributiveLaw (->) f (Cofree f)
forall (f :: * -> *) (h :: * -> *).
(Functor f, Functor h) =>
DistributiveLaw (->) f h -> DistributiveLaw (->) f (Cofree h)
distCofreeT f (f a) -> f (f a)
forall a. a -> a
DistributiveLaw (->) f f
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id) Identity (f a) -> f (Identity a)
DistributiveLaw (->) Identity f
forall (f :: * -> *). Functor f => DistributiveLaw (->) Identity f
seqIdentity GAlgebra (->) (Cofree f) f b
φ ((a -> Identity a) -> f a -> f (Identity a)
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Identity a
forall a. a -> Identity a
Identity (f a -> f (Identity a))
-> Coalgebra (->) f a -> GCoalgebra (->) Identity f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Coalgebra (->) f a
ψ)

-- | Unlike most `Unsafe.hylo`s, `elgot` composes an algebra and coalgebra in a
--   way that allows information to move between them. The coalgebra can return,
--   effectively, a pre-folded branch, short-circuiting parts of the process.
elgot :: (Functor f) => Algebra (->) f b -> ElgotCoalgebra (->) (Either b) f a -> a -> b
elgot :: forall (f :: * -> *) b a.
Functor f =>
Algebra (->) f b -> ElgotCoalgebra (->) (Either b) f a -> a -> b
elgot Algebra (->) f b
φ ElgotCoalgebra (->) (Either b) f a
ψ = Algebra (->) (Compose (Either b) f) b
-> Coalgebra (->) (Compose (Either b) f) a -> a -> b
forall (f :: * -> *) b a.
Functor f =>
Algebra (->) f b -> Coalgebra (->) f a -> a -> b
Unsafe.hylo (Either b b -> b
forall a. Either a a -> a
fromEither (Either b b -> b)
-> (Compose (Either b) f b -> Either b b)
-> Algebra (->) (Compose (Either b) f) b
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Algebra (->) f b -> Either b (f b) -> Either b b
forall b c a. (b -> c) -> Either a b -> Either a c
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second Algebra (->) f b
φ (Either b (f b) -> Either b b)
-> (Compose (Either b) f b -> Either b (f b))
-> Compose (Either b) f b
-> Either b b
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Compose (Either b) f b -> Either b (f b)
forall {k1} {k2} (f :: k1 -> *) (g :: k2 -> k1) (a :: k2).
Compose f g a -> f (g a)
getCompose) (Either b (f a) -> Compose (Either b) f a
forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose (Either b (f a) -> Compose (Either b) f a)
-> ElgotCoalgebra (->) (Either b) f a
-> Coalgebra (->) (Compose (Either b) f) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ElgotCoalgebra (->) (Either b) f a
ψ)

-- | The dual of `elgot`, `coelgot` allows the /algebra/ to short-circuit in
--   some cases – operating directly on a part of the seed.
coelgot :: (Functor f) => ElgotAlgebra (->) (Pair a) f b -> Coalgebra (->) f a -> a -> b
coelgot :: forall (f :: * -> *) a b.
Functor f =>
ElgotAlgebra (->) (Pair a) f b -> Coalgebra (->) f a -> a -> b
coelgot ElgotAlgebra (->) (Pair a) f b
φ Coalgebra (->) f a
ψ = Algebra (->) (Compose (Pair a) f) b
-> Coalgebra (->) (Compose (Pair a) f) a -> a -> b
forall (f :: * -> *) b a.
Functor f =>
Algebra (->) f b -> Coalgebra (->) f a -> a -> b
Unsafe.hylo (ElgotAlgebra (->) (Pair a) f b
φ ElgotAlgebra (->) (Pair a) f b
-> (Compose (Pair a) f b -> Pair a (f b))
-> Algebra (->) (Compose (Pair a) f) b
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Compose (Pair a) f b -> Pair a (f b)
forall {k1} {k2} (f :: k1 -> *) (g :: k2 -> k1) (a :: k2).
Compose f g a -> f (g a)
getCompose) (Pair a (f a) -> Compose (Pair a) f a
forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose (Pair a (f a) -> Compose (Pair a) f a)
-> (a -> Pair a (f a)) -> Coalgebra (->) (Compose (Pair a) f) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Coalgebra (->) f a -> Pair a a -> Pair a (f a)
forall b c a. (b -> c) -> Pair a b -> Pair a c
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second Coalgebra (->) f a
ψ (Pair a a -> Pair a (f a)) -> (a -> Pair a a) -> a -> Pair a (f a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> Pair a a
forall a. a -> Pair a a
diagonal)

futu :: (Corecursive (->) t f, Functor f) => GCoalgebra (->) (Free f) f a -> a -> t
futu :: forall t (f :: * -> *) a.
(Corecursive (->) t f, Functor f) =>
GCoalgebra (->) (Free f) f a -> a -> t
futu = DistributiveLaw (->) (FreeT f Identity) f
-> GCoalgebra (->) (FreeT f Identity) f a -> a -> t
forall t (f :: * -> *) (m :: * -> *) a.
(Corecursive (->) t f, Functor f, Monad m) =>
DistributiveLaw (->) m f -> GCoalgebra (->) m f a -> a -> t
gana (DistributiveLaw (->) f f
-> DistributiveLaw (->) (FreeT f Identity) f
forall (f :: * -> *) (h :: * -> *).
(Functor f, Functor h) =>
DistributiveLaw (->) h f -> DistributiveLaw (->) (Free h) f
Unsafe.seqFreeT f (f a) -> f (f a)
forall a. a -> a
DistributiveLaw (->) f f
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id)

gprepro ::
  (Steppable (->) t f, Recursive (->) t f, Functor f, Comonad w) =>
  DistributiveLaw (->) f w ->
  GAlgebra (->) w f a ->
  (forall x. f x -> f x) ->
  t ->
  a
gprepro :: forall t (f :: * -> *) (w :: * -> *) a.
(Steppable (->) t f, Recursive (->) t f, Functor f, Comonad w) =>
DistributiveLaw (->) f w
-> GAlgebra (->) w f a -> (forall x. f x -> f x) -> t -> a
gprepro DistributiveLaw (->) f w
k GAlgebra (->) w f a
φ forall x. f x -> f x
e =
  DistributiveLaw (->) f w
-> DistributiveLaw (->) Identity f
-> GAlgebra (->) w f a
-> GCoalgebra (->) Identity f t
-> t
-> a
forall (w :: * -> *) (m :: * -> *) (f :: * -> *) b a.
(Comonad w, Monad m, Functor f) =>
DistributiveLaw (->) f w
-> DistributiveLaw (->) m f
-> GAlgebra (->) w f b
-> GCoalgebra (->) m f a
-> a
-> b
Unsafe.ghylo f (w a) -> w (f a)
DistributiveLaw (->) f w
k Identity (f a) -> f (Identity a)
DistributiveLaw (->) Identity f
forall (f :: * -> *). Functor f => DistributiveLaw (->) Identity f
seqIdentity GAlgebra (->) w f a
φ ((t -> Identity t) -> f t -> f (Identity t)
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (t -> Identity t
forall a. a -> Identity a
Identity (t -> Identity t) -> (t -> t) -> t -> Identity t
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Algebra (->) f t -> t -> t
forall a. Algebra (->) f a -> t -> a
forall {k} {k1} (c :: k -> k1 -> *) (t :: k) (f :: k1 -> k)
       (a :: k1).
Recursive c t f =>
Algebra c f a -> c t a
cata (Algebra (->) f t
forall {k} (c :: k -> k -> *) (t :: k) (f :: k -> k).
Steppable c t f =>
Algebra c f t
embed Algebra (->) f t -> (f t -> f t) -> Algebra (->) f t
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. f t -> f t
forall x. f x -> f x
e)) (f t -> f (Identity t))
-> (t -> f t) -> GCoalgebra (->) Identity f t
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. t -> f t
forall {k} {k1} (c :: k -> k1 -> *) (t :: k) (f :: k -> k1).
Projectable c t f =>
Coalgebra c f t
project)

gpostpro ::
  (Steppable (->) t f, Corecursive (->) t f, Functor f, Monad m) =>
  DistributiveLaw (->) m f ->
  (forall x. f x -> f x) ->
  GCoalgebra (->) m f a ->
  a ->
  t
gpostpro :: forall t (f :: * -> *) (m :: * -> *) a.
(Steppable (->) t f, Corecursive (->) t f, Functor f, Monad m) =>
DistributiveLaw (->) m f
-> (forall x. f x -> f x) -> GCoalgebra (->) m f a -> a -> t
gpostpro DistributiveLaw (->) m f
k forall x. f x -> f x
e =
  DistributiveLaw (->) f Identity
-> DistributiveLaw (->) m f
-> GAlgebra (->) Identity f t
-> GCoalgebra (->) m f a
-> a
-> t
forall (w :: * -> *) (m :: * -> *) (f :: * -> *) b a.
(Comonad w, Monad m, Functor f) =>
DistributiveLaw (->) f w
-> DistributiveLaw (->) m f
-> GAlgebra (->) w f b
-> GCoalgebra (->) m f a
-> a
-> b
Unsafe.ghylo f (Identity a) -> Identity (f a)
DistributiveLaw (->) f Identity
forall (f :: * -> *). Functor f => DistributiveLaw (->) f Identity
distIdentity m (f a) -> f (m a)
DistributiveLaw (->) m f
k (Algebra (->) f t
forall {k} (c :: k -> k -> *) (t :: k) (f :: k -> k).
Steppable c t f =>
Algebra c f t
embed Algebra (->) f t
-> (f (Identity t) -> f t) -> GAlgebra (->) Identity f t
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Identity t -> t) -> f (Identity t) -> f t
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Coalgebra (->) f t -> t -> t
forall a. Coalgebra (->) f a -> a -> t
forall {k} {k1} (c :: k -> k1 -> *) (t :: k1) (f :: k -> k1)
       (a :: k).
Corecursive c t f =>
Coalgebra c f a -> c a t
ana (f t -> f t
forall x. f x -> f x
e (f t -> f t) -> Coalgebra (->) f t -> Coalgebra (->) f t
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Coalgebra (->) f t
forall {k} {k1} (c :: k -> k1 -> *) (t :: k) (f :: k -> k1).
Projectable c t f =>
Coalgebra c f t
project) (t -> t) -> (Identity t -> t) -> Identity t -> t
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Identity t -> t
forall a. Identity a -> a
runIdentity))

-- | The metamorphism definition from Gibbons’ paper.
stream :: Coalgebra (->) (XNor c) b -> (b -> a -> b) -> b -> [a] -> [c]
stream :: forall c b a.
Coalgebra (->) (XNor c) b -> (b -> a -> b) -> b -> [a] -> [c]
stream Coalgebra (->) (XNor c) b
f b -> a -> b
g = Coalgebra (->) (XNor c) b
-> (b -> a -> b) -> Coalgebra (->) (XNor c) b -> b -> [a] -> [c]
forall c b a.
Coalgebra (->) (XNor c) b
-> (b -> a -> b) -> Coalgebra (->) (XNor c) b -> b -> [a] -> [c]
fstream Coalgebra (->) (XNor c) b
f b -> a -> b
g (XNor c b -> Coalgebra (->) (XNor c) b
forall a b. a -> b -> a
const XNor c b
forall a b. XNor a b
Neither)

-- | Basically the definition from Gibbons’ paper, except the flusher (@h@) is a
--  `Coalgebra` instead of an `unfold`.
fstream ::
  Coalgebra (->) (XNor c) b ->
  (b -> a -> b) ->
  Coalgebra (->) (XNor c) b ->
  b ->
  [a] ->
  [c]
fstream :: forall c b a.
Coalgebra (->) (XNor c) b
-> (b -> a -> b) -> Coalgebra (->) (XNor c) b -> b -> [a] -> [c]
fstream Coalgebra (->) (XNor c) b
f b -> a -> b
g Coalgebra (->) (XNor c) b
h =
  Coalgebra (->) (XNor c) b
-> CoalgebraM (->) Maybe (XNor c) b
-> (XNor a [a] -> Maybe (Pair (b -> b) [a]))
-> b
-> [a]
-> [c]
forall t (f :: * -> *) u (g :: * -> *) b.
(Projectable (->) t f, Steppable (->) u g, Corecursive (->) u g,
 Functor g) =>
Coalgebra (->) g b
-> CoalgebraM (->) Maybe g b
-> (f t -> Maybe (Pair (b -> b) t))
-> b
-> t
-> u
Unsafe.streamGApo
    Coalgebra (->) (XNor c) b
h
    ( \b
b -> case Coalgebra (->) (XNor c) b
f b
b of
        XNor c b
Neither -> Maybe (XNor c b)
forall a. Maybe a
Nothing
        XNor c b
other -> XNor c b -> Maybe (XNor c b)
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure XNor c b
other
    )
    ( \case
        XNor a [a]
Neither -> Maybe (Pair (b -> b) [a])
forall a. Maybe a
Nothing
        Both a
a [a]
x' -> Pair (b -> b) [a] -> Maybe (Pair (b -> b) [a])
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((b -> a -> b) -> a -> b -> b
forall a b c. (a -> b -> c) -> b -> a -> c
flip b -> a -> b
g a
a (b -> b) -> [a] -> Pair (b -> b) [a]
forall a b. a -> b -> Pair a b
:!: [a]
x')
    )

-- snoc :: [a] -> a -> [a]
-- snoc x a = x ++ [a]

-- x :: [Int]
-- x = stream project snoc [] [1, 2, 3, 4, 5]

-- TODO: Weaken `Monad` constraint to `Applicative`.
cotraverse ::
  ( Steppable (->) t (f a),
    Steppable (->) u (f b),
    Bitraversable f,
    Traversable (f b),
    Monad m
  ) =>
  (a -> m b) ->
  t ->
  m u
cotraverse :: forall t (f :: * -> * -> *) a u b (m :: * -> *).
(Steppable (->) t (f a), Steppable (->) u (f b), Bitraversable f,
 Traversable (f b), Monad m) =>
(a -> m b) -> t -> m u
cotraverse a -> m b
f = CoalgebraM (->) m (f b) t -> t -> m u
forall (m :: * -> *) t (f :: * -> *) a.
(Monad m, Steppable (->) t f, Traversable f) =>
CoalgebraM (->) m f a -> a -> m t
Unsafe.anaM ((a -> m b) -> (t -> m t) -> f a t -> m (f b t)
forall (f :: * -> *) a c b d.
Applicative f =>
(a -> f c) -> (b -> f d) -> f a b -> f (f c d)
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bitraverse a -> m b
f t -> m t
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (f a t -> m (f b t)) -> (t -> f a t) -> CoalgebraM (->) m (f b) t
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. t -> f a t
forall {k} {k1} (c :: k -> k1 -> *) (t :: k) (f :: k -> k1).
Projectable c t f =>
Coalgebra c f t
project)

-- | Zygohistomorphic prepromorphism – everyone’s favorite recursion scheme joke.
zygoHistoPrepro ::
  (Steppable (->) t f, Recursive (->) t f, Functor f) =>
  (f b -> b) ->
  (f (EnvT b (Cofree f) a) -> a) ->
  (forall c. f c -> f c) ->
  t ->
  a
zygoHistoPrepro :: forall t (f :: * -> *) b a.
(Steppable (->) t f, Recursive (->) t f, Functor f) =>
(f b -> b)
-> (f (EnvT b (Cofree f) a) -> a)
-> (forall c. f c -> f c)
-> t
-> a
zygoHistoPrepro f b -> b
φ' = DistributiveLaw (->) f (EnvT b (Cofree f))
-> (f (EnvT b (Cofree f) a) -> a)
-> (forall c. f c -> f c)
-> t
-> a
forall t (f :: * -> *) (w :: * -> *) a.
(Steppable (->) t f, Recursive (->) t f, Functor f, Comonad w) =>
DistributiveLaw (->) f w
-> GAlgebra (->) w f a -> (forall x. f x -> f x) -> t -> a
gprepro ((f b -> b)
-> DistributiveLaw (->) f (Cofree f)
-> DistributiveLaw (->) f (EnvT b (Cofree f))
forall (f :: * -> *) a (w :: * -> *).
Functor f =>
Algebra (->) f a
-> DistributiveLaw (->) f w -> DistributiveLaw (->) f (EnvT a w)
distEnvT f b -> b
φ' (DistributiveLaw (->) f f -> DistributiveLaw (->) f (Cofree f)
forall (f :: * -> *) (h :: * -> *).
(Functor f, Functor h) =>
DistributiveLaw (->) f h -> DistributiveLaw (->) f (Cofree h)
distCofreeT f (f a) -> f (f a)
forall a. a -> a
DistributiveLaw (->) f f
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id))