module Data.BranchingStream ( Strf(..) , hdf , tlf , genStrf , strfToList ) where import Control.Comonad {-| An H-branching stream. The specific functor chosen for /H/ determines its behavior: * @Strf 'Id'@ is an infinite stream * @Strf Maybe@ is a non-empty stream * @Strf []@ is a rose tree -} data Strf h c = Consf c (h (Strf h c)) hdf :: Strf h c -> c hdf (Consf x _) = x tlf :: Strf h c -> h (Strf h c) tlf (Consf _ xs) = xs genStrf :: Functor h => (a -> c) -> (a -> h a) -> a -> Strf h c genStrf g1 g2 z = Consf (g1 z) (fmap (genStrf g1 g2) (g2 z)) instance Functor h => Functor (Strf h) where fmap g = genStrf (g . hdf) tlf instance Functor h => Comonad (Strf h) where extract = hdf duplicate = genStrf id tlf strfToList :: Strf Maybe a -> [a] strfToList (Consf x xs) = x : maybe [] strfToList xs