srtree-2.0.0.0: src/Data/SRTree/Recursion.hs
{-# language RankNTypes #-}
{-# language DeriveFunctor #-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.SRTree.Recursion
-- Copyright : (c) Fabricio Olivetti 2021 - 2024
-- License : BSD3
-- Maintainer : fabricio.olivetti@gmail.com
-- Stability : experimental
-- Portability : FlexibleInstances, DeriveFunctor, ScopedTypeVariables
--
-- Recursion schemes
--
-----------------------------------------------------------------------------
module Data.SRTree.Recursion where
import Control.Monad ( (>=>) )
data ListF a b = NilF | ConsF a b deriving Functor
data NatF a = ZeroF | SuccF a deriving Functor
data StreamF a b = StreamF a b deriving Functor
data TreeF a b = LeafF | NodeF b a b deriving Functor
newtype Fix f = Fix {unfix :: f (Fix f)}
type Algebra f a = f a -> a
type CoAlgebra f a = a -> f a
data Cofree f a = a :< f (Cofree f a)
data Free f a = Ret a | Op (f (Free f a))
extract :: Cofree f a -> a
extract (x :< _) = x
unOp :: Free f a -> f (Free f a)
unOp (Op x) = x
unOp _ = error "partial function unOp called on Ret"
cata :: Functor f => (f a -> a) -> Fix f -> a
cata alg = alg . fmap (cata alg) . unfix
--zigzag :: Functor f => (f a -> a) -> Fix f -> a
--zigzag alg =
cataM :: (Functor f, Monad m) => (forall x . f (m x) -> m (f x)) -> (f a -> m a) -> Fix f -> m a
cataM seq alg = cata (seq >=> alg)
ana :: Functor f => (a -> f a) -> a -> Fix f
ana coalg = Fix . fmap (ana coalg) . coalg
hylo :: Functor f => (f b -> b) -> (a -> f a) -> a -> b
hylo alg coalg = alg . fmap (cata alg . ana coalg) . coalg
para :: Functor f => (f (Fix f, a) -> a) -> Fix f -> a
para alg = alg . fmap (id &&& para alg) . unfix
where (f &&& g) x = (f x, g x)
mutu :: Functor f => (f (a, b) -> a) -> (f (a, b) -> b) -> (Fix f -> a, Fix f -> b)
mutu alg1 alg2 = (fst . cata alg, snd . cata alg)
where alg x = (alg1 x, alg2 x)
apo :: Functor f => (a -> f (Either (Fix f) a)) -> a -> Fix f
apo coalg = Fix . fmap (id ||| apo coalg) . coalg
where
(f ||| g) (Left x) = f x
(f ||| g) (Right y) = g y
accu :: Functor f => (forall x. f x -> p -> f (x, p)) -> (f a -> p -> a) -> Fix f -> p -> a
accu st alg (Fix t) p = alg (fmap (uncurry (accu st alg)) (st t p)) p
histo :: Functor f => (f (Cofree f a) -> a) -> Fix f -> a
histo alg = extract . cata (\x -> alg x :< x)
futu :: Functor f => (a -> f (Free f a)) -> a -> Fix f
futu coalg = ana coalg' . Ret
where
coalg' (Ret a) = coalg a
coalg' (Op k) = k
chrono :: Functor f => (f (Cofree f b) -> b) -> (a -> f (Free f a)) -> a -> b
chrono alg coalg = extract . hylo alg' coalg' . Ret
where
alg' x = alg x :< x
coalg' (Ret a) = coalg a
coalg' (Op k) = k
fromList :: [a] -> Fix (ListF a)
fromList [] = Fix NilF
fromList (x:xs) = Fix (ConsF x (fromList xs))
toList :: Fix (ListF a) -> [a]
toList (Fix NilF) = []
toList (Fix (ConsF x xs)) = x : toList xs
stream2list :: StreamF a [a] -> [a]
stream2list (StreamF x y) = x : y
toNat :: Int -> Fix NatF
toNat 0 = Fix ZeroF
toNat n = Fix (SuccF (toNat (n-1)))
fromNat :: Fix NatF -> Int
fromNat (Fix ZeroF) = 0
fromNat (Fix (SuccF x)) = 1 + fromNat x