<div dir="ltr">Hi Petr,<div><br></div><div style>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.)</div>
<div style><br></div><div style>Happy hacking,</div><div style>-Iavor</div><div style><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, Jan 27, 2013 at 12:30 PM, Petr P <span dir="ltr">&lt;<a href="mailto:petr.mvd@gmail.com" target="_blank">petr.mvd@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">  Dear maintainers,<br><div class="gmail_quote"><div dir="ltr"><div><br></div><div>I have two suggestions for <span style="background-color:yellow">MonadWriter</span>:</div>
<div><br></div><div>(1) Remove the &quot;<span style="background-color:yellow">Monoid</span> w&quot; constraint from the definition.</div>


<div><br></div><div>The <span style="background-color:yellow">constraints</span> prevent creating new instances of the class that have only an implied <span style="background-color:yellow">monoid</span>. 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.</div>



<div><br></div><div>The constraint is meant to ensure that instances of that class obey the <span style="background-color:yellow">monad</span> laws. But it&#39;s not the responsibility of a type class that its instances satisfy the laws. They could violate them even without this <span style="background-color:yellow">constraints</span>. Instead, this constraint should be specified (and it is) in the definition of their instances.</div>



<div><br></div><div>It has been discussed in <span style="background-color:yellow">haskell</span>-cafe &lt;<a href="http://www" target="_blank">http://www</a>.<span style="background-color:yellow">haskell</span>.org/<span style="background-color:yellow">pipermail</span>/<span style="background-color:yellow">haskell</span>-cafe/2012-December/thread.html#105088&gt; with <span style="background-color:yellow">arguments</span> for and against.</div>



<div><br></div><div><br></div><div>(2) Add</div><div><br></div><div><font face="courier new, monospace">  -- | @contained m@ executes the action @m@ in a contained environment and</font></div><div>
<font face="courier new, monospace">  -- returns its value and its output. The current output is not modified.  </font></div><div><font face="courier new, monospace">  contained :: m a -&gt; m (a, w)</font><br></div>
<div><br></div><div>to MonadWriter.</div><div><br></div><div>This generalizes &quot;pass&quot; and &quot;listen&quot;  and has it&#39;s a sort of inverse to &quot;writer&quot; with these simple laws:</div>
<div><div><br></div><div><font face="courier new, monospace">  writer &lt;=&lt; contained   = id</font></div><div><font face="courier new, monospace">  contained . writer     = return</font><br></div></div><div>
<br></div><div>It seems as a understandable set of laws that its instances should obey.</div><div><br></div><div>It also expresses the same concept as &quot;runWriterT&quot; does, but inside the type class. In particular, for &quot;WriterT&quot; we have</div>



<div><font face="courier new, monospace"><br></font></div><div><div><font face="courier new, monospace">  contained :: (Monoid w, Monad m) =&gt; WriterT w m a -&gt; WriterT w m (a, w)</font></div><div><font face="courier new, monospace">  contained = lift . runWriterT</font></div>



</div><div><br></div><div>Current instances won&#39;t be affected as &quot;contained&quot; can be expressed using &quot;pass&quot; and &quot;listen&quot; (and vice versa).</div><div>Full details available at</div>
<div><a href="https://github.com/ppetr/mtl/compare/9cc075cfaa40028a54f1dedf62af67e912f9fd42...master" target="_blank">https://github.com/ppetr/mtl/compare/9cc075cfaa40028a54f1dedf62af67e912f9fd42...master</a><br></div><div>


[There &quot;contained&quot; is expressed without the &quot;Monoid w&quot; constraint as suggested in (1). If we keep the constraint, &quot;contained&quot; can be expressed more simply as</div><div><font face="courier new, monospace">  containde k = pass (listen k &gt;&gt;= \x -&gt; return (x, const mempty</font><font face="courier new, monospace">))</font>.</div>


<div><br></div><div>Also, &quot;contained&quot; isn&#39;t probably a good name, I just couldn&#39;t think of anything better.]</div><div><br></div><div><br></div><div>   Best regards,</div>
<div>   Petr Pudlak</div></div>
</div><br></div>
<br>_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/libraries" target="_blank">http://www.haskell.org/mailman/listinfo/libraries</a><br>
<br></blockquote></div><br></div>