I don&#39;t quite understand how this would work.  For example, would it work for these examples?<div><br></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  do x &lt;- blah</font></div><div>

<font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     let foo = return</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     foo (f x)  -- Using an alias of return/pure</font></div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  do x &lt;- Just blah   </font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     Just (f x)  </font>-- another form of aliasing</div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  do x &lt;- blah</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     return (g x x)  -- could perhaps be turned into:</font></div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                     -- (\x -&gt; g x x) &lt;$&gt; blah</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br>

</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  do x &lt;- blah</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     y &lt;- return x</font></div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     return (f y)    -- = f &lt;$&gt; blah ?</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  do x1 &lt;- foo1        -- effect order must not be reversed</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     x2 &lt;- foo2</font></div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     return (f x2 x1)  -- note reversed order</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  -- multiple uses of applicative</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  do x1 &lt;- foo1</font></div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     y &lt;- return (f x1)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     x2 &lt;- foo2</font></div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     y2 &lt;- return (g y x2)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     return y2</font></div>

<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div>So I guess it&#39;s possible to detect the pattern:</div><div><br></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  do x1 &lt;- foo1; ...; xN &lt;- fooN; [res &lt;-] return (f {x1..xN})</font></div>

<div><br></div><div>where {x1..xN} means &quot;x1..xN&quot; in some order&quot; and turn it into:</div><div><br></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  do [res &lt;-] (\x1..xN -&gt; f {x1..xN}) &lt;$&gt; foo1 &lt;*&gt; ... &lt;*&gt; fooN</font></div>

<div><br></div><div>Open issues would be detection of the correct &quot;return&quot;-like thing.  This is why using monad comprehensions would help somewhat, but not fully because it&#39;s still possible to put &quot;x &lt;- return y&quot; in the generators part.  The current desugaring of do-notation is very simple because it doesn&#39;t even need to know about the monad laws.  They are used implicitly by the optimiser (e.g., &quot;foo &gt;&gt;= \x -&gt; return x&quot; is optimised to just &quot;foo&quot; after inlining), but the desugarer doesn&#39;t need to know about them.</div>

<div><br></div><div><br></div><div><div><div class="gmail_quote">On 4 September 2011 03:34, Daniel Peebles <span dir="ltr">&lt;<a href="mailto:pumpkingod@gmail.com">pumpkingod@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;">

Hi all,<div><br></div><div>I was wondering what people thought of a smarter do notation. Currently, there&#39;s an almost trivial desugaring of do notation into (&gt;&gt;=), (&gt;&gt;), and fail (grr!) which seem to naturally imply Monads (although oddly enough, return is never used in the desugaring). The simplicity of the desugaring is nice, but in many cases people write monadic code that could easily have been Applicative.</div>


<div><br></div><div>For example, if I write in a do block:</div><div><br></div><div>x &lt;- action1</div><div>y &lt;- action2</div><div>z &lt;- action3</div><div>return (f x y z)</div><div><br></div><div>that doesn&#39;t require any of the context-sensitivty that Monads give you, and could be processed a lot more efficiently by a clever Applicative instance (a parser, for instance). Furthermore, if return values are ignored, we could use the (&lt;$), (&lt;*), or (*&gt;) operators which could make the whole thing even more efficient in some instances.</div>


<div><br></div><div>Of course, the fact that the return method is explicitly mentioned in my example suggests that unless we do some real voodoo, Applicative would have to be a superclass of Monad for this to make sense. But with the new default superclass instances people are talking about in GHC, that doesn&#39;t seem too unlikely in the near future.</div>


<div><br></div><div>On the implementation side, it seems fairly straightforward to determine whether Applicative is enough for a given do block. Does anyone have any opinions on whether this would be a worthwhile change? The downsides seem to be a more complex desugaring pass (although still something most people could perform in their heads), and some instability with making small changes to the code in a do block. If you make a small change to use a variable before the return, you instantly jump from Applicative to Monad and might break types in your program. I&#39;m not convinced that&#39;s necessary a bad thing, though.</div>


<div><br></div><div>Any thoughts?</div><div><br></div><div>Thanks,</div><div>Dan</div>
<br>_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br>Push the envelope. Watch it bend.<br>
</div></div>