The streaming package defines a Stream
type that looks like the following:
data Stream f m r
= Step !(f (Stream f m r))
| Effect (m (Stream f m r))
| Return r
There is a comment on the Stream
type that says the following:
The
Stream
data type is equivalent toFreeT
and can represent any effectful succession of steps, where the form of the steps or 'commands' is specified by the first (functor) parameter.
I'm wondering how the Stream
type is equivalent to FreeT
?
Here is the definition of FreeT
:
data FreeF f a b = Pure a | Free (f b)
newtype FreeT f m a = FreeT { runFreeT :: m (FreeF f a (FreeT f m a)) }
It looks like it is not possible to create an isomorphism between these two types.
To be specific, I don't see a way to write the following two functions that makes them an isomorphism:
freeTToStream :: FreeT f m a -> Stream f m a
streamToFreeT :: Stream f m a -> FreeT f m a
For instance, I'm not sure how to express a value like Return "hello" :: Stream f m String
as a FreeT
.
I guess it could be done like the following, but the Pure "hello"
is necessarily going to be wrapped in an m
, while in Return "hello" :: Stream f m String
it is not:
FreeT $ pure $ Pure "hello" :: Applicative m => FreeT f m a
Can Stream
be considered equivalent to FreeT
even though it doesn't appear possible to create an isomorphism between them?
FreeT
andStream
(which is calledFStream
in the code). This should make it easy for anyone that wants to play around with this. This code is from Ivan Miljenovic's workshop on the streaming library at Lambda Jam 2018. – TrimurtiFreeT (Const ()) IO ()
has no equivalent offoo :: Stream (Const ()) IO () ; foo = Effect $ putStrLn "hello world" >> pure foo
. What might be possible is showing that everyStream
is equivalent to someFreeT
over a different functor/monad pair. – Agnesagnese