suggestions for improving MonadWriter

Iavor Diatchki iavor.diatchki at gmail.com
Mon Jan 28 07:18:06 CET 2013


Hi Petr,

you might also consider using `monadLib`, it is an alternative to MTL that
I and some of my colleagues have used for a few years now.  It does both of
the things that you suggest (i.e., the `Monoid` constraints are on the
instances, not the class, and it provides a method to gather collected
output, in `monadLib` this operation is called `collect`).  Generally
`monadLib` provides similar functionality to MTL but with a number of
improvements like the ones you suggest (e.g., same functionality with fewer
types, improved support for working with continuations, a correct
implementation of backtracking, etc.)

Happy hacking,
-Iavor



On Sun, Jan 27, 2013 at 12:30 PM, Petr P <petr.mvd at gmail.com> wrote:

>   Dear maintainers,
>
> I have two suggestions for MonadWriter:
>
> (1) Remove the "Monoid w" constraint from the definition.
>
> The constraints prevent creating new instances of the class that have
> only an implied monoid. For example, I needed to create a simple writer
> which always stores the last written element. I had to wrap it into Last,
> which was a nuisance for users of my library. Without the constraint, my
> instance would be quite simpler and still satisfying all the laws. There
> are many other similar use cases, like counting the number of written
> values (and disregarding their actual content) etc.
>
> The constraint is meant to ensure that instances of that class obey the
> monad laws. But it's not the responsibility of a type class that its
> instances satisfy the laws. They could violate them even without this
> constraints. Instead, this constraint should be specified (and it is) in
> the definition of their instances.
>
> It has been discussed in haskell-cafe <http://www.haskell.org/pipermail/
> haskell-cafe/2012-December/thread.html#105088> with arguments for and
> against.
>
>
> (2) Add
>
>   -- | @contained m@ executes the action @m@ in a contained environment
> and
>   -- returns its value and its output. The current output is not
> modified.
>   contained :: m a -> m (a, w)
>
> to MonadWriter.
>
> This generalizes "pass" and "listen"  and has it's a sort of inverse to
> "writer" with these simple laws:
>
>   writer <=< contained   = id
>   contained . writer     = return
>
> It seems as a understandable set of laws that its instances should obey.
>
> It also expresses the same concept as "runWriterT" does, but inside the
> type class. In particular, for "WriterT" we have
>
>   contained :: (Monoid w, Monad m) => WriterT w m a -> WriterT w m (a, w)
>   contained = lift . runWriterT
>
> Current instances won't be affected as "contained" can be expressed using
> "pass" and "listen" (and vice versa).
> Full details available at
>
> https://github.com/ppetr/mtl/compare/9cc075cfaa40028a54f1dedf62af67e912f9fd42...master
> [There "contained" is expressed without the "Monoid w" constraint as
> suggested in (1). If we keep the constraint, "contained" can be expressed
> more simply as
>   containde k = pass (listen k >>= \x -> return (x, const mempty)).
>
> Also, "contained" isn't probably a good name, I just couldn't think of
> anything better.]
>
>
>    Best regards,
>    Petr Pudlak
>
>
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/libraries/attachments/20130127/e9f94755/attachment.htm>


More information about the Libraries mailing list