[Haskell-cafe] Smarter do notation
Thomas Schilling
nominolo at googlemail.com
Sun Sep 4 18:28:27 CEST 2011
I don't quite understand how this would work. For example, would it work
for these examples?
do x <- blah
let foo = return
foo (f x) -- Using an alias of return/pure
do x <- Just blah
Just (f x) -- another form of aliasing
do x <- blah
return (g x x) -- could perhaps be turned into:
-- (\x -> g x x) <$> blah
do x <- blah
y <- return x
return (f y) -- = f <$> blah ?
do x1 <- foo1 -- effect order must not be reversed
x2 <- foo2
return (f x2 x1) -- note reversed order
-- multiple uses of applicative
do x1 <- foo1
y <- return (f x1)
x2 <- foo2
y2 <- return (g y x2)
return y2
So I guess it's possible to detect the pattern:
do x1 <- foo1; ...; xN <- fooN; [res <-] return (f {x1..xN})
where {x1..xN} means "x1..xN" in some order" and turn it into:
do [res <-] (\x1..xN -> f {x1..xN}) <$> foo1 <*> ... <*> fooN
Open issues would be detection of the correct "return"-like thing. This is
why using monad comprehensions would help somewhat, but not fully because
it's still possible to put "x <- return y" in the generators part. The
current desugaring of do-notation is very simple because it doesn't even
need to know about the monad laws. They are used implicitly by the
optimiser (e.g., "foo >>= \x -> return x" is optimised to just "foo" after
inlining), but the desugarer doesn't need to know about them.
On 4 September 2011 03:34, Daniel Peebles <pumpkingod at gmail.com> wrote:
> Hi all,
>
> I was wondering what people thought of a smarter do notation. Currently,
> there's an almost trivial desugaring of do notation into (>>=), (>>), 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.
>
> For example, if I write in a do block:
>
> x <- action1
> y <- action2
> z <- action3
> return (f x y z)
>
> that doesn'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 (<$), (<*), or (*>) operators which could make the
> whole thing even more efficient in some instances.
>
> 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't seem too
> unlikely in the near future.
>
> 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'm not convinced that's necessary a bad
> thing, though.
>
> Any thoughts?
>
> Thanks,
> Dan
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>
--
Push the envelope. Watch it bend.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110904/a8267119/attachment.htm>
More information about the Haskell-Cafe
mailing list