<div dir="ltr">Edward,<div class="gmail_extra"><br><div class="gmail_quote">2013/1/28 Edward A <span class="" style>Kmett</span> <span dir="ltr">&lt;<a href="mailto:ekmett@gmail.com" target="_blank"><span class="" style>ekmett</span>@gmail.com</a>&gt;</span><br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="auto"><div>I&#39;ve often wanted to remove the Monoid constraint, so I&#39;m a strong +1 on the first one.</div>

<div><br></div><div>The second one I&#39;m -1 on, given that it can be expressed with the existing combinators and due in small part to a more ideological concern:</div><div><br></div><div>Over time I&#39;ve come to view cramming pass/listen and local into the respective MonadWriter and MonadReader classes as a mistake. If we had the hierarchy to do over, I&#39;d probably want them split into separate subclasses. This would permit more instances involving Cont, logging to disk, etc.</div>

</div></blockquote><div><br></div><div style>I strongly support your idea. Currently, <span class="" style>MonadWriter</span> and <span class="" style>MonadReader</span> just reflect <span class="" style>ReaderT</span> and <span class="" style>WriterT</span> so that we can make <span class="" style>monad</span> stacks. But they don&#39;t reflect the ideas - a <span class="" style>monad</span> we write to or read from, without any additional constraints. I&#39;d really love to have them split up: A more general class that has just &#39;tell&#39; and &#39;writer&#39;, and another that also has &#39;listen&#39; and &#39;pass&#39; (perhaps also &#39;contained&#39;).</div>

<div style>I tried to discuss it in <span class="" style>haskell</span>-cafe once &lt;<a href="http://www.mail-archive.com/haskell-cafe@haskell.org/msg101756.html">http://www.mail-archive.com/<span class="" style>haskell</span>-cafe@<span class="" style>haskell</span>.org/msg101756.html</a>&gt;, but without any feedback on the idea, so I thought everybody is happy with the current state.</div>

<div style><br></div><div style>In this case, it seems that nothing important would break by this change, because IMHO there are very very little custom instances of MonadWriter/Reader. I&#39;m also a big fan of this proposal: <a href="http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances">http://<span class="" style>hackage</span>.<span class="" style>haskell</span>.org/<span class="" style>trac</span>/<span class="" style>ghc</span>/wiki/<span class="" style>DefaultSuperclassInstances</span></a></div>

<div style>If it were implemented and standardized, we could refactor type classes without breaking existing code (or breaking it just very little).</div><div style>[In particular, it&#39;d be possible to make <span class="" style>Monad</span> a subclass of Applicative, something I&#39;ve always regretted we don&#39;t have.]</div>

<div style><br></div><div style>Other than that, I&#39;m not sure how adding &quot;contained&quot; goes against this idea. If we split MonadWriter into two type classes, &quot;contained&quot; would simply go into the one with &quot;listen&quot; and &quot;pass&quot;.</div>

<div style><br></div><div style>Best regards,</div><div style>Petr</div><div style><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<div dir="auto"><div><br></div><div>Also, the former can be done purely within the mtl, while the latter drags transformers into it.</div></div></blockquote><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<div dir="auto"><div><span class=""><font color="#888888"><br><br>-Edward</font></span></div><div><div class="h5"><div><br>On Jan 27, 2013, at 3:30 PM, Petr P &lt;<a href="mailto:petr.mvd@gmail.com" target="_blank">petr.mvd@gmail.com</a>&gt; wrote:<br>

<br></div><blockquote type="cite"><div><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>
</div></blockquote></div></div><div class="im"><blockquote type="cite"><div><span>_______________________________________________</span><br><span>Libraries mailing list</span><br><span><a href="mailto:Libraries@haskell.org" target="_blank">Libraries@haskell.org</a></span><br>

<span><a href="http://www.haskell.org/mailman/listinfo/libraries" target="_blank">http://www.haskell.org/mailman/listinfo/libraries</a></span><br></div></blockquote></div></div></blockquote></div><br></div></div>