In the comments to this question, it has been mentioned that nesting several layers of FreeT transformers (each with a different functor) can serve a similar purpose to the "Data types à la carte" approach (that combines the functors themselves using coproducts) despite the two approaches not being isomorphic.
My question is: where does the difference lie? Are there cases that one approach can handle, but not the other? Do they admit different interpreters?
Update: Here's a simple example of nested FreeT
transformers. Augmenting a computation with the ability to emit log messages and request delays:
import Data.Functor.Identity
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Free
import Control.Concurrent
type Delay = Int
type DelayT = FreeT ((,) Delay)
delay :: Monad m => Delay -> DelayT m ()
delay t = liftF (t,())
type Message = String
type LogT = FreeT ((,) Message)
emitLog :: Monad m => Message -> LogT m ()
emitLog msg = liftF (msg,())
type Effected = DelayT (LogT Identity)
program :: Effected Char
program = lift (emitLog "foo") >> delay 1000 >> return 'c'
interpret :: Effected a -> IO a
interpret = (iterT $ \(d,a)->threadDelay d >> a)
. hoistFreeT (iterT $ \(m,a)->putStrLn m >> a)
. hoistFreeT (hoistFreeT (return . runIdentity))
main :: IO ()
main = interpret program >>= putChar
(This particular example could have been made even simpler by using Producer
s from the pipes
package, which are a particular kind of free monad transformers.)
I'm not 100% confident in my own understanding of this, so if anyone notices anything (blatantly) wrong, please point it out.
Starting with Extensible Effects, the Eff
type is basically isomorphic to:
data Eff :: [* -> *] -> * -> * where
Pure :: a -> Eff es a
Side :: Union es (Eff es a) -> Eff es a
where Union es a
is a union/sum type of the list of types es
parameterized by a
. Union
is isomorphic to repeated applications of :+:
from Data Types a la Carte. To sum (!) it all up, Eff
seems to be an optimized version of Data Types a la Carte.
We may conclude that the differences between monad transformers and extensible effects described in the paper apply here. In particular, free monad transformer stacks cannot interleave effects, while Data Types a la Carte/Extensible Effects can.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With