[GHC] #13875: ApplicativeDo desugaring is lazier than standard desugaring

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.3 Keywords: ApplicativeDo | Operating System: Unknown/Multiple Architecture: | Type of failure: Other Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Suppose I write {{{#!hs import Data.Maybe (isJust) bangy m = do (_,_) <- m return () main = print $ isJust (bangy (Just undefined)) }}} If I compile this with `ApplicativeDo`, it prints `True`. Otherwise, it throws an exception. The basic problem is that the (correct) `bangy` function ''requires'' a `Monad` constraint, but `ApplicativeDo` replaces it with a lazier function that can get by with `Functor`. I believe it should desugar correctly, and impose a `Monad` constraint here. To get the `Functor` constraint should require an explicit lazy pattern match: {{{#!hs bangy m = do ~(_,_) <- m return () }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

Applicative do-notation desugaring preserves the original semantics,
#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by dfeuer): Note that the documentation indicates provided that the `Applicative` instance satisfies `<*> = ap` and `pure = return` (these are true of all the common monadic types). Thus, you can normally turn on `-XApplicativeDo` without fear of breaking your program. There is one pitfall to watch out for; see Things to watch out for. This is simply not true at the moment. The "Things to watch out for" section is unrelated. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: (none) Type: bug | Status: new Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by dfeuer): * priority: normal => high * milestone: 8.4.1 => 8.2.1 Comment: I'm setting a milestone of 8.2.1 and high priority to at least ''document'' what the extension actually does right now. If the powers that be want to fix it, then we can set a milestone of 8.4 for the fix if necessary. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: (none) Type: bug | Status: new Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonmar): Wow, you're right. I hadn't realised this, and I think you're the first person to point it out. It's not limited to `Functor`, the problem occurs with `Applicative` too: {{{ Prelude Data.Maybe> :set -XApplicativeDo Prelude Data.Maybe> let f m = do () <- m; () <- m; return () Prelude Data.Maybe> :t f f :: Applicative f => f () -> f () Prelude Data.Maybe> isJust (f (Just undefined)) True }}} To fix this properly we would have to prevent `ApplicativeDo` from applying to any statement with a strict pattern match. In practice I doubt anyone is going to write `~p` to make `ApplicativeDo` work, but fortunately it still works for simple variable patterns. Ugh, I don't know what the best fix is here, but I agree at the very least we need some documentation. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: new Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonpj): * owner: (none) => simonmar Comment: It's a subtle issue, not described in the paper. So yes we need something in the user manual, but a longer Note somewhere, linking to this ticket, giving example(s), and explaining our design choice, would be helpful.
To fix this properly we would have to prevent ApplicativeDo from applying to any statement with a strict pattern match.
That would not be hard, would it? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: new Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by dfeuer): Replying to [comment:3 simonmar]:
To fix this properly we would have to prevent `ApplicativeDo` from applying to any statement with a strict pattern match. In practice I doubt anyone is going to write `~p` to make `ApplicativeDo` work, but fortunately it still works for simple variable patterns.
It seems terribly unfortunate, in my opinion, if adding a language extension to a module can, ''all by itself'', introduce a memory leak. The fix does seem annoying, but I don't think there's another good way. The current behavior is both surprising and inconsistent. We generally expect, for example, that {{{#!hs (x,y) <- m e }}} will be exactly the same as {{{#!hs xy <- m case xy of (x,y) -> e }}} but that's not currently the case. Here's an (arguably) more extreme example: {{{#!hs oops m = do !xy <- m pure (fst xy + snd xy) }}} With `ApplicativeDo`, the bang pattern is silently ignored. So I think the special desugaring should only be used if all the patterns are lazy. It might make sense to check whether an expression could ''otherwise'' be desugared specially, and offer an optional warning in that case. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: new Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by dfeuer): Yet another few thoughts. This is a situation that could be improved offering, in addition, separate `ado` syntax. Such syntax would offer deeply-lazy-always pattern matching, prohibit inappropriate bangs, and throw an error if desugaring would require `>>=`. Along with setting laziness appropriately, this would allow the user to declare that they expect applicative optimizations to kick in, even when a monad is actually available. While I'm mentioning idle thoughts: monad comprehension syntax seems to handle the `pure`/`return`/`pure $`/whatever issue a lot more cleanly than anything `do`-like. Has anyone considered applicative comprehensions? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: new Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonmar): This bug makes #13242 moot, incidentally. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: new Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3681 Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonmar): * differential: => Phab:D3681 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: new Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3681 Wiki Page: | -------------------------------------+------------------------------------- Comment (by Iceland_jack): I have long had an idea for an `ado`, restricting the `do`-notation to be `Applicative` or weaker. It would make the user intent's clearer, "this should not have a `Monad` constraint" and paves the way for a wealth of Shakespearean puns -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: patch Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3681 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: new => patch -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring
-------------------------------------+-------------------------------------
Reporter: dfeuer | Owner: simonmar
Type: bug | Status: patch
Priority: high | Milestone: 8.2.1
Component: Compiler | Version: 8.3
Resolution: | Keywords: ApplicativeDo
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: Other | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s): Phab:D3681
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ben Gamari

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: merge Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3681 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: patch => merge -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: closed Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: fixed | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3681 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: merge => closed * resolution: => fixed Comment: Merged to `ghc-8.2` with 97aa533fd8bcbd8e42b3358e8a07423ad2a2d01f. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring
-------------------------------------+-------------------------------------
Reporter: dfeuer | Owner: simonmar
Type: bug | Status: closed
Priority: high | Milestone: 8.2.1
Component: Compiler | Version: 8.3
Resolution: fixed | Keywords: ApplicativeDo
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: Other | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s): Phab:D3681
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ben Gamari

#13875: ApplicativeDo desugaring is lazier than standard desugaring
-------------------------------------+-------------------------------------
Reporter: dfeuer | Owner: simonmar
Type: bug | Status: closed
Priority: high | Milestone: 8.2.1
Component: Compiler | Version: 8.3
Resolution: fixed | Keywords: ApplicativeDo
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: Other | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s): Phab:D3681
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ben Gamari

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: closed Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: fixed | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3681 Wiki Page: | -------------------------------------+------------------------------------- Comment (by ElvishJerricco): Replying to [comment:6 dfeuer]:
While I'm mentioning idle thoughts: monad comprehension syntax seems to handle the `pure`/`return`/`pure $`/whatever issue a lot more cleanly than anything `do`-like. Has anyone considered applicative comprehensions?
This may no longer be the right place to answer this question, but I do think that using `in` would be better than special casing `return`, `pure`, and `$`. {{{ do a <- foo b <- bar in a + b }}} Seems more consistent with `let`-binding syntax. Though there is definitely some value in desugarring those functions since it means `ApplicativeDo` can be a drop-in optimization. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:16 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: simonmar Type: bug | Status: closed Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.3 Resolution: fixed | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3681 Wiki Page: | -------------------------------------+------------------------------------- Comment (by andrewthad): I'm not sure if this has already been done, but the "Existentials patterns and GADTs" section of the user manual should probably be removed. https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts... #existential-patterns-and-gadts -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13875#comment:17 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13875: ApplicativeDo desugaring is lazier than standard desugaring
-------------------------------------+-------------------------------------
Reporter: dfeuer | Owner: simonmar
Type: bug | Status: closed
Priority: high | Milestone: 8.2.1
Component: Compiler | Version: 8.3
Resolution: fixed | Keywords: ApplicativeDo
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: Other | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s): Phab:D3681
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Simon Marlow
participants (1)
-
GHC