[Haskell-cafe] Demarcating monad transformers.
Nickolay Kudasov
nickolay.kudasov at gmail.com
Sat Sep 21 00:23:44 CEST 2013
Hi Café,
Below I describe what I call «demarcating monad transformer». It works
great for my purposes, though the construction feels a bit awkward.
Perhaps, this is just an instance of a general case. For details and
example, see [1] (single module package).
Recently I got a challenge of manipulating transformed monadic values. In
my case the value was of type t (Free f) a (or MonadFree m => t m a).
The challange itself was to provide a function:
transform :: (Functor f, MonadTrans t) => (forall b. f b -> t (Free f)
b) -> t (Free f) a -> t (Free f) a
The type t (Free f) a for my purposes can be read as «a program with
low-level API specified with functor f and extra features specified with
monad transformer t».
transform takes a “basic transformation” phi and an abstract program p and
applies phi whenever p “executes” command of free functor f.
It turns out that this function is impossible (try StateT). The point is
that you can't “get inside” of transformed monadic value.
So I came up with idea of «demarcating» monad transformer. By «demarcating»
I mean separating pure monadic computations (lifted m a) from transformed
ones (t m a).
Such separation can be made explicit with the help of free monads:
data DemarcateF t m next
= forall b. DemarcateMonad (m b) (b -> next) -- "pure" monadic
computation
| forall b. DemarcateTrans (t m b) (b -> next) -- transformed
monadic computation
instance Functor (Demarcate t m) where ...
-- getting monad for freenewtype Demarcate t m a = Demarcate {
unDemarcate :: Free (DemarcateF t m) a }
instance Monad (Demarcate t m) where ...instance MonadTrans (Demarcate
t) where ...
With that I can define transform functions:
-- transform arbitrary monadic computationtransformDemarcateM ::
(forall b. m b -> Demarcate t m b) -> Demarcate t m a -> Demarcate t m
a
-- transform free monadic actionstransformDemarcateFree :: (forall b.
f b -> Demarcate t (Free f) b) -> Demarcate t (Free f) a -> Demarcate
t (Free f) atransformDemarcateFree phi = transformDemarcateM (iterM
phi)
The complete code is available at [1]. Check out examples/simple.hs for a
use case.
Now the questions are:
- has anyone else encountered such a challenge?
- is this solution an instance of a more general pattern?
- is it sensible to use Demarcate t m a when m is not a free monad?
- how Demarcate may affect the performance?
Thanks in advance,
Nick
[1] <https://github.com/fizruk/demarcate>https://github.com/fizruk/demarcate
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130921/84db7b3e/attachment.htm>
More information about the Haskell-Cafe
mailing list