data-fresh-0.2013.250.1: src/Control/Monad/Trans/Fresh/Stream.hs
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.Monad.Trans.Fresh.Stream where
import Control.Applicative
import Control.Arrow (first)
import Control.Comonad.Cofree
import Control.Monad.Trans.Class
import Data.Fresh
import Data.Functor.Identity
newtype FreshT v m a = FreshT
{ runFreshT :: Cofree Identity v -> m (a, Cofree Identity v) }
-- | Creates a @Cofree Identity v@, based on a seed, and a function to split it.
seedStream
:: v -- ^ Stream seed
-> (v -> v) -- ^ Successor
-> Cofree Identity v
seedStream seed sukk = go seed
where
go tt = tt `seq` (mm :< Identity (go mm))
where
mm = sukk tt
-- | A stream of integers.
integerStream :: Integer -> Cofree Identity Integer
integerStream n = seedStream n succ
-- | Creates a @Cofree Identity v@ based on an infinite list.
--
-- This function will cause an error when the list turns out to be finite.
listStream :: [v] -> Cofree Identity v
listStream (x:xs) = x :< Identity (listStream xs)
listStream [] = error "Can't create a stream from a finite list."
instance Functor m => Functor (FreshT v m) where
fmap f (FreshT xx) = FreshT $ \s -> fmap (first f) (xx s)
instance (Functor m, Monad m) => Applicative (FreshT v m) where
pure = return
FreshT ff <*> FreshT xx = FreshT $ \s -> do
(fv, s1) <- ff s
(xv, s2) <- xx s1
return (fv xv, s2)
instance Monad m => Monad (FreshT v m) where
return x = FreshT $ \s -> return (x, s)
FreshT aa >>= f = FreshT $ \s -> do
(a, s1) <- aa s
let FreshT ff = f a
ff s1
-- TODO Alternative, MonadPlus
-- TODO MonadFix
instance MonadTrans (FreshT v) where
lift m = FreshT $ \s -> do
r <- m
return (r, s)
-- TODO MonadIO
instance Applicative m => Fresh v (FreshT v m) where
fresh = FreshT $ \(s :< Identity s') -> pure (s, s')