[GHC] #13511: ApplicativeDo incorrectly requiring Monad

#13511: ApplicativeDo incorrectly requiring Monad -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.2 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- We ran into this bug in production, this is a simplified reproduction. The following program will not type check, requiring an unnecessary Monad instance: {{{ {-# LANGUAGE ApplicativeDo, GeneralizedNewtypeDeriving #-} import Data.Functor.Identity import Data.Monoid newtype A x = A (Identity x) deriving (Functor, Applicative) shouldWork :: A () shouldWork = do a <- pure () b <- pure () let ab = a <> b return ab }}} {{{ pepe:~/code/snippets$ ghci ApplicativeDoBug.hs GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help [1 of 1] Compiling Main ( ApplicativeDoBug.hs, interpreted ) ApplicativeDoBug.hs:10:14: error: • No instance for (Monad A) arising from a do statement • In the expression: do { a <- pure (); b <- pure (); let ab = a <> b; return ab } In an equation for ‘shouldWork’: shouldWork = do { a <- pure (); b <- pure (); let ab = ...; return ab } Failed, modules loaded: none. }}} There is a simple workaround, which worked for us in production: {{{ workaround :: A () workaround = do a <- pure () b <- pure () return $ let ab = a <> b in ab }}} I asked in #ghc and it seems this is not yet fixed in HEAD. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13511: ApplicativeDo incorrectly requiring Monad -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * cc: simonmar (added) * keywords: => ApplicativeDo -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13511: ApplicativeDo incorrectly requiring Monad -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by rwbarton): * type: bug => feature request Comment: The user's guide makes it pretty clear that a case like this is not currently expected to work. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

In general, the rule for when a do statement incurs a Monad constraint is as follows. If the do-expression has the following form: {{{ do p1 <- E1; ...; pn <- En; return E }}} where none of the variables defined by p1...pn are mentioned in E1...En,
#13511: ApplicativeDo incorrectly requiring Monad -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by mnislaih): The user's guide doesn't explicitly mention let bindings, it only says: then the expression will only require Applicative. Otherwise, the expression will require Monad. The block may return a pure expression E depending upon the results p1...pn with either return or pure. Or were you referring to something else ? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13511: ApplicativeDo return case doesn't handle lets -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * milestone: => 8.4.1 Comment: Perhaps the users guide language could be improved. Currently the `return` case is a rather narrow, purely syntactic rewrite which does not handle `let`s. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13511: ApplicativeDo return case doesn't handle lets -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by mnislaih): If we stick to the definition of ApplicativeDo in the users guide, and given that join is not needed here, I think it is fair to say that this is a bug:
The language option -XApplicativeDo enables an alternative translation for the do-notation, which uses the operators <$>, <*>, along with join as far as possible.
-- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13511: ApplicativeDo return case doesn't handle lets -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): simonmar: do you know what is happening here? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13511: ApplicativeDo return case doesn't handle lets -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonmar): The `do` expression doesn't match the requirements as described in the docs, so I don't think it's a bug. Perhaps we could expand the heuristics to handle this case, but then the docs would get more complicated, and where does it end? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13511: ApplicativeDo return case doesn't handle lets -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by mnislaih): Fair enough. I wasn't aware that Applicativedo didn't handle let bindings, and neither was anyone in #ghc for what it's worth. The docs ought to make this more evident. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13511: ApplicativeDo return case doesn't handle lets -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonmar): It depends what you mean by "doesn't handle". It does have some heuristics to collect let bindings and prevent them from causing spurious dependencies, but that's aimed more at using Applicative with Monad, rather than the Applicative-only context. If there's a way to expand the desugaring that would also be simple to describe, then I wouldn't be averse to adding it. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13511: ApplicativeDo return case doesn't handle lets -------------------------------------+------------------------------------- Reporter: mnislaih | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.6.1 Component: Compiler | Version: 8.0.2 Resolution: | Keywords: ApplicativeDo Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by chshersh): I experienced similar issue with `-XApplicativeDo` while using `-XRecordWildCards` and `optparse-applicative` library. What I wanted to write: {{{#!hs data Options = Options { reportTime :: Integer } optionsParser :: Parser Options optionsParser = do hours <- option auto $ long "hours" minutes <- option auto $ long "minutes" let reportTime = hours * 60 + minutes pure Options{..} }}} What helped is to write it like this: {{{#!hs data Options = Options { reportTime :: Integer } optionsParser :: Parser Options optionsParser = do hours <- option auto $ long "hours" minutes <- option auto $ long "minutes" pure Options{ reportTime = hours * 60 + minutes } }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13511#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC