Skip to content

Commit

Permalink
Improve metamorphism documentation (#51)
Browse files Browse the repository at this point in the history
Also makes some other doc & formatting changes in the vicinity.

And this adds `gapo` as a documentation aid, making this a minor bump
for Yaya.
  • Loading branch information
sellout committed Apr 3, 2024
2 parents 1a88688 + 6a6e668 commit 47467e5
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 71 deletions.
6 changes: 3 additions & 3 deletions core/src/Yaya/Fold.hs
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,9 @@ steppableReadPrec = steppableReadPrec' liftReadPrec

-- | A fixed-point operator for inductive / finite data structures.
--
-- *NB*: This is only guaranteed to be finite when @f a@ is strict in @a@
-- (having strict functors won't prevent `Nu` from being lazy). Using
-- @-XStrictData@ can help with this a lot.
-- __NB__: This is only guaranteed to be finite when @f a@ is strict in @a@
-- (having strict functors won't prevent `Nu` from being lazy). Using
-- @-XStrictData@ can help with this a lot.
newtype Mu f = Mu (forall a. Algebra (->) f a -> a)

instance (Functor f) => Projectable (->) (Mu f) f where
Expand Down
7 changes: 4 additions & 3 deletions core/src/Yaya/Fold/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,10 @@ height = (+ 1) . foldr max (-1)
-- | When folded, returns the number of nodes in the data structure.
--
-- __NB__: This is /not/ the same as the length when applied to a list. I.e.,
-- @`length` xs + 1 == `cata` `size` xs@, because this is counting the
-- nodes of the structure (how many `Neither`s and `Both`s), not how
-- many elements (which would be equivalent to only counting `Both`s).
-- @`Data.List.length` xs `+` 1 `==` `Yaya.Fold.cata` `size` xs@,
-- because this is counting the nodes of the structure (how many
-- `Neither`s and `Both`s), not how many elements (which would be
-- equivalent to only counting `Both`s).
size :: (Foldable f) => f Natural -> Natural
size = foldr (+) 1

Expand Down
39 changes: 28 additions & 11 deletions core/src/Yaya/Zoo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module Yaya.Zoo
comap,
comutu,
contramap,
gapo,
gmutu,
histo,
insidePartial,
Expand Down Expand Up @@ -45,6 +46,7 @@ import "profunctors" Data.Profunctor (Profunctor (lmap))
import "this" Yaya.Fold
( Algebra,
AlgebraM,
Coalgebra,
Corecursive (ana),
DistributiveLaw,
GAlgebra,
Expand Down Expand Up @@ -75,14 +77,26 @@ import "this" Yaya.Pattern
uncurry,
)

-- | A generalized form of `apo`, where, rather than returning a complete
-- branch, you can return a value of another type, provided there is a
-- corresponding `Coalgebra` to expand the value into the same fixed-point
-- result type.
gapo ::
(Corecursive (->) t f, Functor f) =>
Coalgebra (->) f b ->
GCoalgebra (->) (Either b) f a ->
a ->
t
gapo ψ = gana $ seqEither ψ

-- | A recursion scheme that allows you to return a complete branch when
-- unfolding.
apo ::
(Projectable (->) t f, Corecursive (->) t f, Functor f) =>
GCoalgebra (->) (Either t) f a ->
a ->
t
apo = gana (seqEither project)
apo = gapo project

-- | If you have a monadic algebra, you can fold it by distributing the monad
-- over the algebra.
Expand All @@ -91,7 +105,7 @@ cataM ::
AlgebraM (->) m f a ->
t ->
m a
cataM φ = cata <=< sequenceA)
cataM = cata . (<=< sequenceA)

-- | A recursion scheme that allows two algebras to see each others’ results. (A
-- generalization of `zygo`.) This is an example that falls outside the scope
Expand Down Expand Up @@ -122,7 +136,9 @@ gmutu w v φ' φ = extract . mutu (lowerEnv w φ') (lowerEnv v φ)
let a = fst p
in fmap (a :!:) (snd p)

-- | This could use a better name.
-- | As the name implies, this is the dual of `mutu`, and thus generalizes
-- `gapo`. Each coalgebra can return a value of an alternative type, which
-- causes expansion to continue with the other coalgebra.
comutu ::
(Corecursive (->) t f, Functor f) =>
GCoalgebra (->) (Either a) f b ->
Expand Down Expand Up @@ -162,8 +178,9 @@ mutuM ::
m a
mutuM φ' φ = fmap snd . cataM (bisequence . bimap (φ' . fmap swap) φ . diagonal)

histo :: (Recursive (->) t f, Functor f) => GAlgebra (->) (Cofree f) f a -> t -> a
histo = gcata (distCofreeT id)
histo ::
(Recursive (->) t f, Functor f) => GAlgebra (->) (Cofree f) f a -> t -> a
histo = gcata $ distCofreeT id

-- | A recursion scheme that gives you access to the original structure as you
-- fold. (A specialization of `zygo`.)
Expand All @@ -172,7 +189,7 @@ para ::
GAlgebra (->) (Pair t) f a ->
t ->
a
para = gcata (distTuple embed)
para = zygo embed

-- | A recursion scheme that uses a “helper algebra” to provide additional
-- information when folding. (A generalization of `para`, and specialization
Expand All @@ -183,18 +200,18 @@ zygo ::
GAlgebra (->) (Pair b) f a ->
t ->
a
zygo φ = gcata (distTuple φ)
zygo φ = gcata $ distTuple φ

-- | This definition is different from the one given by `gcataM (distTuple φ')`
-- because it has a monadic “helper” algebra. But at least it gives us the
-- opportunity to show how `zygo` is a specialization of `mutu`.
-- | This definition is different from the one given by @`gcataM` `.`
-- `distTuple`@ because it has a monadic “helper” algebra. But at least it
-- gives us the opportunity to show how `zygo` is a specialization of `mutu`.
zygoM ::
(Monad m, Recursive (->) t f, Traversable f) =>
AlgebraM (->) m f b ->
GAlgebraM (->) m (Pair b) f a ->
t ->
m a
zygoM φ' = mutuM (φ' . fmap snd)
zygoM = mutuM . (. fmap snd)

-- | Potentially-infinite lists, like `[]`.
type Colist a = Nu (XNor a)
Expand Down
2 changes: 1 addition & 1 deletion core/yaya.cabal
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cabal-version: 3.0

name: yaya
version: 0.6.1.0
version: 0.6.2.0
synopsis: Total recursion schemes.
description: Recursion schemes allow you to separate recursion from your
business logic – making your own operations simpler, more modular,
Expand Down
18 changes: 10 additions & 8 deletions hedgehog/src/Yaya/Hedgehog/Fold.hs
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,7 @@ law_cataCompose Proxy φ ε =

-- | Creates a generator for any `Steppable` type whose pattern functor has
-- terminal cases (e.g., not `Data.Functor.Identity` or `((,) a)`). @leaf@ can
-- only generate terminal cases, and `branch` can generate any case. If the
-- provided `branch` generates terminal cases, then the resulting tree may
-- have a height less than the `Size`, otherwise it will be a perfect tree
-- with a height of exactly the provided `Size`.
-- only generate terminal cases, and @branch@ can generate any case.
--
-- This is similar to `Gen.recursive` in that it separates the non-recursive
-- cases from the recursive ones, except
Expand All @@ -124,15 +121,20 @@ law_cataCompose Proxy φ ε =
-- * the non-recursive cases aren’t included in recursive calls (see above for
-- why).
--
-- If there’s no existing @Gen (f Void)@ for your pattern functor, you can
-- If there’s no existing @`Gen` (f `Void`)@ for your pattern functor, you can
-- either create one manually, or pass `Hedgehog.Gen.discard` to the usual
-- @Gen a -> Gen (f a)@ generator.
-- @`Gen` a -> `Gen` (f a)@ generator.
--
-- NB: Hedgehog’s `Size` is signed, so this can raise an exception if given a
-- negative `Size`.
-- __NB__: Hedgehog’s `Size` is signed, so this can raise an exception if given
-- a negative `Size`.
embeddableOfHeight ::
(Steppable (->) t f, Functor f) =>
-- | A generator for terminal cases (leaf nodes).
Gen (f Void) ->
-- | A generator for arbitrary cases. If the provided value generates terminal
-- cases, then the resulting tree may have a height less than the `Size`,
-- otherwise it will be a perfect tree with a height of exactly the provided
-- `Size`.
(Gen t -> Gen (f t)) ->
Size ->
Gen t
Expand Down
2 changes: 1 addition & 1 deletion hedgehog/yaya-hedgehog.cabal
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cabal-version: 3.0

name: yaya-hedgehog
version: 0.3.0.1
version: 0.3.0.2
synopsis: Hedgehog testing support for the Yaya recursion scheme
library.
description: If you use Yaya in your own code and have tests written
Expand Down
Loading

0 comments on commit 47467e5

Please sign in to comment.