yaya-0.5.2.1: src/Yaya/Fold/Native.hs
{-# LANGUAGE Safe #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- | Uses of recursion schemes that use Haskell’s built-in recursion in a total
-- manner.
module Yaya.Fold.Native
( module Yaya.Fold.Native.Internal,
Fix (Fix, unFix),
distCofreeT,
)
where
import "base" Control.Category (Category ((.)))
import "base" Data.Bifunctor (Bifunctor (bimap))
import "base" Data.Eq (Eq ((==)))
import "base" Data.Foldable (Foldable (toList))
import "base" Data.Function (($))
import "base" Data.Functor (Functor (fmap))
import "base" Data.Functor.Classes (Eq1, Show1)
import "base" Data.List.NonEmpty (NonEmpty ((:|)))
import "base" Numeric.Natural (Natural)
import "base" Text.Show (Show (showsPrec))
import "comonad" Control.Comonad (Comonad (extract))
import "comonad" Control.Comonad.Trans.Env (EnvT (EnvT), runEnvT)
import "free" Control.Comonad.Cofree (Cofree ((:<)), unwrap)
import "free" Control.Monad.Trans.Free (Free, FreeF (Free, Pure), free)
import "strict" Data.Strict.Classes (Strict (toStrict))
import "this" Yaya.Fold
( Corecursive (ana),
DistributiveLaw,
Projectable (project),
Recursive (cata),
Steppable (embed),
recursiveEq,
recursiveShowsPrec,
)
import "this" Yaya.Fold.Common (diagonal)
import "this" Yaya.Fold.Native.Internal (Cofix (unCofix))
import "this" Yaya.Pattern
( AndMaybe (Indeed, Only),
Maybe,
XNor (Both, Neither),
uncurry,
)
-- | A fixed-point constructor that uses Haskell's built-in recursion. This is
-- strict/recursive.
newtype Fix f = Fix {unFix :: f (Fix f)}
instance Projectable (->) (Fix f) f where
project = unFix
instance Steppable (->) (Fix f) f where
embed = Fix
instance (Functor f) => Recursive (->) (Fix f) f where
cata ɸ = ɸ . fmap (cata ɸ) . project
instance (Functor f, Foldable f, Eq1 f) => Eq (Fix f) where
(==) = recursiveEq
instance (Functor f, Show1 f) => Show (Fix f) where
showsPrec = recursiveShowsPrec
instance Recursive (->) Natural Maybe where
cata ɸ = ɸ . fmap (cata ɸ) . project
instance Corecursive (->) [a] (XNor a) where
ana ψ =
( \case
Neither -> []
Both h t -> h : ana ψ t
)
. ψ
instance Corecursive (->) (NonEmpty a) (AndMaybe a) where
ana ψ =
( \case
Only h -> h :| []
Indeed h t -> h :| toList @NonEmpty (ana ψ t)
)
. ψ
instance (Functor f) => Corecursive (->) (Free f a) (FreeF f a) where
ana ψ =
free
. ( \case
Pure a -> Pure a
Free fb -> Free . fmap (ana ψ) $ fb
)
. ψ
instance (Functor f) => Corecursive (->) (Cofree f a) (EnvT a f) where
ana ψ = uncurry (:<) . fmap (fmap (ana ψ)) . toStrict . runEnvT . ψ
distCofreeT ::
(Functor f, Functor h) =>
DistributiveLaw (->) f h ->
DistributiveLaw (->) f (Cofree h)
distCofreeT k =
ana $ uncurry EnvT . bimap (fmap extract) (k . fmap unwrap) . diagonal