yaya-unsafe-0.1.1.0: src/Yaya/Unsafe/Fold/Instances.hs
-- | Type class instances that use direct recursion in a potentially partial
-- way. This is separated from the rest of `Yaya.Unsafe.Fold` because you can
-- neither control nor qualify the import of instances. Therefore this module
-- is _extra_ dangerous, as having these instances available applies to the
-- entire module they’re imported into.
--
-- This contains instances that you might _expect_ to see, but which aren’t
-- actually total. For example, folding a lazy list `[a]` is _not_ guaranteed
-- to terminate.
module Yaya.Unsafe.Fold.Instances where
import Control.Arrow
import Control.Comonad
import Control.Comonad.Cofree
import Control.Comonad.Env
import Control.Monad
import Control.Monad.Trans.Free
import Data.Functor.Classes
import Data.List.NonEmpty
import Yaya.Fold
import Yaya.Fold.Native
import Yaya.Pattern
import qualified Yaya.Unsafe.Fold as Unsafe
instance Functor f => Recursive (Fix f) f where
cata = flip Unsafe.hylo 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 Functor f => Corecursive (Mu f) f where
ana = Unsafe.hylo embed
instance Functor f => Recursive (Nu f) f where
cata = flip Unsafe.hylo project
instance (Functor f, Foldable f, Eq1 f) => Eq (Nu f) where
(==) = recursiveEq
instance (Functor f, Show1 f) => Show (Nu f) where
showsPrec = recursiveShowsPrec
instance Recursive [a] (XNor a) where
cata = flip Unsafe.hylo project
instance Recursive (NonEmpty a) (AndMaybe a) where
cata = flip Unsafe.hylo project
instance Functor f => Recursive (Cofree f a) (EnvT a f) where
cata = flip Unsafe.hylo project
instance Functor f => Recursive (Free f a) (FreeF f a) where
cata = flip Unsafe.hylo project
-- TODO: If we can generalize this to an arbitrary 'Recursive t (FreeF h a)'
-- then it would no longer be unsafe.
seqFreeT
:: (Functor f, Functor h)
=> DistributiveLaw h f
-> DistributiveLaw (Free h) f
seqFreeT k =
cata
(\case
Pure a -> free . Pure <$> a
Free ft -> free . Free <$> k ft)