[Haskell-cafe] Monad transformer responsibilities

wren ng thornton wren at freegeek.org
Fri Jun 5 19:38:17 EDT 2009


Martijn van Steenbergen wrote:
> Hello,
> 
> Suppose I have two projects: 1) one that defines a monad transformer and 
> an accompanying type class that captures my monad-specific operations 
> and 2) one that uses the other project, combining the monad transformer 
> with, say, Parsec.
> 
> Now while writing my Parsec parser I want to use my monad transformer 
> operations without using lift: I need an instance MyMonadT Parsec. Where 
> should this instance go? I can think of three answers, all unsatisfactory:
> 
> 1) For obvious reasons it shouldn't go in the Parsec package.
> 
> 2) For pretty much the same reasons it shouldn't go in my monad 
> transformer package, either. Also, it is undesirable to add a dependency 
> on Parsec just for this instance, and the package should not have to 
> know about the projects that are going to use it.
> 
> 3) If I put it in the second project it is an orphan instance, which is 
> undesirable for well-known reasons.
> 
> What is the best solution?

4) Define a newtype of MyMonadT Parsec and declare instances of MyMonad 
and Parsec for it.

Yes, I know Parsec is (an alias for) a data type, not a type class. But 
for the general problem, using newtype wrappers is often the best 
solution when it's possible. This is one of the reasons why it's good to 
define type classes for specialty monads rather than hard-wiring the 
types of functions to use the one concrete instance. (For instance, this 
is one of the things that rocks about the LogicT library; you can add a 
StateT on top of a MonadLogic and it all works great.)


For the actual case of Parsec, you could try defining a GenParser class 
and giving it all the combinators as methods, but that's a good deal of 
work and may not scale to your task.

-- 
Live well,
~wren


More information about the Haskell-Cafe mailing list