GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2024-03-11T17:38:47Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/18313ApplicativeDo and RebindableSyntax requires *both* return and pure2024-03-11T17:38:47ZRichard Eisenbergrae@richarde.devApplicativeDo and RebindableSyntax requires *both* return and pure`-XApplicativeDo` applies special treatment to `do`-blocks whose last statement is a call to `return` or `pure`. With `-XRebindableSyntax`, the `return`/`pure` is the one in scope, not the one from the `Prelude`. But this means that this...`-XApplicativeDo` applies special treatment to `do`-blocks whose last statement is a call to `return` or `pure`. With `-XRebindableSyntax`, the `return`/`pure` is the one in scope, not the one from the `Prelude`. But this means that this combination of extensions requires a user to define *both* `return` *and* `pure`. This is silly; if one isn't in scope, we should simply not look for it.
Here is a test case:
```hs
{-# LANGUAGE RebindableSyntax, ApplicativeDo #-}
module Bug where
_ >> _ = ()
return _ = ()
_ <*> _ = ()
fmap _ _ = ()
x = do x
return x
```
This currently fails with
```
Bug.hs:10:5: error: Not in scope: ‘pure’
|
10 | x = do x
| ^^^^...
```
but I think it should succeed.
Sidenote: changing to `x = do x` is accepted, but I have no idea *why* it doesn't look for `pure` in a one-line `do`. Maybe that's special-cased. But it's not documented.https://gitlab.haskell.org/ghc/ghc/-/issues/17768ApplicativeDo breaks compilation with polymorphic bindings2023-07-25T14:21:43ZKirill Elaginkirelagin@gmail.comApplicativeDo breaks compilation with polymorphic bindings## Summary
A valid code that uses a let binding with an explicit Rank2 type stops compiling when `ApplicativeDo` is enabled.
## Steps to reproduce
```haskell
{-# LANGUAGE ApplicativeDo, Rank2Types #-}
module Test where
type M = fora...## Summary
A valid code that uses a let binding with an explicit Rank2 type stops compiling when `ApplicativeDo` is enabled.
## Steps to reproduce
```haskell
{-# LANGUAGE ApplicativeDo, Rank2Types #-}
module Test where
type M = forall m. Monad m => m () -> m ()
runM :: M -> IO ()
runM m = m $ pure ()
q :: IO ()
q = do
() <- pure ()
let
m :: M
m = id
() <- pure ()
runM m
-- pure ()
```
Note that the example is very fragile. It will start to compile if you either:
* Remove `ApplicativeDo`
* Uncomment the last `pure`
* Remove one of the `pure`
* Reorder the `pure`s and `let`
The error is:
```
foo.hs:14:3-4: error:
• Ambiguous type variable ‘m0’ arising from a use of ‘m’
prevents the constraint ‘(Monad m0)’ from being solved.
<...>
• In the first argument of ‘return’, namely ‘m’
In the expression:
do () <- pure ()
let m :: M
m = id
() <- pure ()
runM m
In an equation for ‘q’:
q = do () <- pure ()
let m :: M
....
() <- pure ()
runM m
|
14 | () <- pure ()
| ^^
foo.hs:19:8: error:
• Couldn't match type ‘m’ with ‘m0’
‘m’ is a rigid type variable bound by
a type expected by the context:
M
at foo.hs:19:3-8
Expected type: m () -> m ()
Actual type: m0 () -> m0 ()
• In the first argument of ‘runM’, namely ‘m’
In a stmt of a 'do' block: runM m
In the expression:
do () <- pure ()
let m :: M
m = id
() <- pure ()
runM m
• Relevant bindings include
m :: m0 () -> m0 () (bound at foo.hs:17:5)
|
19 | runM m
```
The renamer outputs:
```
= do join (m_aXe <- do () <- pure ()
let m_aXe :: Test.M
m_aXe = id
return m_aXe |
() <- pure ())
Test.runM m_aXe
```
which I couldn’t make sense of, but it looks like it is getting deshugared to something like:
```
q2 :: IO ()
q2 = let {m :: M; m = id} in return m >>= runM
```
which doesn’t compile indeed.
## Expected behavior
Code that compiles without `ApplicativeDo` should compile with `ApplicativeDo`.
## Environment
* GHC version used: 8.6.5, 8.8.2
Optional:
* Operating System:
* System Architecture:https://gitlab.haskell.org/ghc/ghc/-/issues/13511ApplicativeDo return case doesn't handle lets2022-09-16T23:26:30ZmnislaihApplicativeDo return case doesn't handle letsWe 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.Funct...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.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"ApplicativeDo incorrectly requiring Monad","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"We ran into this bug in production, this is a simplified reproduction. The following program will not type check, requiring an unnecessary Monad instance:\r\n\r\n{{{\r\n{-# LANGUAGE ApplicativeDo, GeneralizedNewtypeDeriving #-}\r\n\r\nimport Data.Functor.Identity\r\nimport Data.Monoid\r\n\r\nnewtype A x = A (Identity x) deriving (Functor, Applicative)\r\n\r\nshouldWork :: A ()\r\nshouldWork = do\r\n a <- pure ()\r\n b <- pure ()\r\n let ab = a <> b\r\n return ab\r\n}}}\r\n\r\n{{{\r\npepe:~/code/snippets$ ghci ApplicativeDoBug.hs \r\nGHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help\r\n[1 of 1] Compiling Main ( ApplicativeDoBug.hs, interpreted )\r\n\r\nApplicativeDoBug.hs:10:14: error:\r\n • No instance for (Monad A) arising from a do statement\r\n • In the expression:\r\n do { a <- pure ();\r\n b <- pure ();\r\n let ab = a <> b;\r\n return ab }\r\n In an equation for ‘shouldWork’:\r\n shouldWork\r\n = do { a <- pure ();\r\n b <- pure ();\r\n let ab = ...;\r\n return ab }\r\nFailed, modules loaded: none.\r\n}}}\r\n\r\nThere is a simple workaround, which worked for us in production:\r\n{{{\r\nworkaround :: A ()\r\nworkaround = do\r\n a <- pure ()\r\n b <- pure ()\r\n return $\r\n let ab = a <> b\r\n in ab\r\n}}}\r\n\r\nI asked in #ghc and it seems this is not yet fixed in HEAD.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/24418Add a warning when ApplicativeDo changes to monadic do2024-02-16T06:52:41ZhololeapAdd a warning when ApplicativeDo changes to monadic doCould we please get a warning when a module that has ApplicativeDo enabled is using monadic do instead? I understand this would be an annoying warning for -Wall, but it could be useful to enable per-module so that you know when a do bloc...Could we please get a warning when a module that has ApplicativeDo enabled is using monadic do instead? I understand this would be an annoying warning for -Wall, but it could be useful to enable per-module so that you know when a do block is using a Monad instance instead of an Applicative instance. Currently, there doesn't seem to be any sort of user feedback to indicate this change and there are many subtle things that can trigger this behavior.https://gitlab.haskell.org/ghc/ghc/-/issues/24406Applicative Do should go via HsExpansion Route2024-03-28T05:02:38ZApoorv IngleApplicative Do should go via HsExpansion Route## Summary
Impredicativity does not play well with `do`-blocks expanding under `ApplicativeDo` Language pragma due to ill-designed `tcSyntaxOp` (c.f. issues documented in [wiki page](https://gitlab.haskell.org/ghc/ghc/-/wikis/Rebindable...## Summary
Impredicativity does not play well with `do`-blocks expanding under `ApplicativeDo` Language pragma due to ill-designed `tcSyntaxOp` (c.f. issues documented in [wiki page](https://gitlab.haskell.org/ghc/ghc/-/wikis/Rebindable-syntax))
## Steps to reproduce
```haskell
-- test.hs
{-# LANGUAGE ImpredicativeTypes, ApplicativeDo #-}
module T where
t :: IO (forall a. a -> a)
t = return id
p :: (forall a. a -> a) -> (Bool, Int)
p f = (f True, f 3)
-- This typechecks (with QL)
foo1 = t >>= \x -> return (p x)
-- But this does *not* type check:
foo2 = do { x <- t ; return (p x) }
```
```
$ ghc test.hs
```
Error:
```
test.hs:14:18: error: [GHC-91028]
• Couldn't match type ‘a0’ with ‘forall a. a -> a’
Expected: IO a0
Actual: IO (forall a. a -> a)
Cannot instantiate unification variable ‘a0’
with a type involving polytypes: forall a. a -> a
• In a stmt of a 'do' block: x <- t
In the expression:
do x <- t
return (p x)
In an equation for ‘foo2’:
foo2
= do x <- t
return (p x)
|
14 | foo2 = do { x <- t ; return (p x) }
| ^
test.hs:14:32: error: [GHC-46956]
• Couldn't match expected type ‘a -> a’ with actual type ‘a0’
because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
forall a. a -> a
at test.hs:14:32
• In the first argument of ‘p’, namely ‘x’
In a stmt of a 'do' block: return (p x)
In the expression:
do x <- t
return (p x)
• Relevant bindings include x :: a0 (bound at test.hs:14:13)
|
14 | foo2 = do { x <- t ; return (p x) }
```
## Expected behavior
It should type check and execute as expected
## Environment
* GHC version used: 9.6, 9.9Apoorv IngleApoorv Inglehttps://gitlab.haskell.org/ghc/ghc/-/issues/23692ApplicativeDo breaks typechecking2023-07-25T14:22:12ZSergey VinokurovApplicativeDo breaks typechecking## Summary
When enabling the `ApplicativeDo` extension the provided program ceases to typecheck. It does work in 9.4.5 and does work if I move `putStrLn` around or remove it entirely, which is surprising. Removing `ApplicativeDo` extens...## Summary
When enabling the `ApplicativeDo` extension the provided program ceases to typecheck. It does work in 9.4.5 and does work if I move `putStrLn` around or remove it entirely, which is surprising. Removing `ApplicativeDo` extension also helps but I'd like to get its effects in `parseCommandLine` function (omitted here for brevity).
## Steps to reproduce
Compile the following program.
Original program:
```haskell
{-# LANGUAGE ApplicativeDo #-}
module Main (main) where
import Control.Monad
data Command
= PolyCmd
| VanillaCmd
data CommonConfig = CommonConfig
{ ccVerbose :: Bool
}
parseCommandline :: IO (CommonConfig, Command)
parseCommandline = undefined
locateHelper :: FilePath -> IO (Maybe FilePath)
locateHelper = undefined
complexWrapper :: IO a -> IO a
complexWrapper = undefined
vanillaRun :: IO ()
vanillaRun = pure ()
polyRun :: (forall a. IO a -> IO a) -> IO ()
polyRun f = f $ pure ()
main :: IO ()
main = do
(config, cmd) <- parseCommandline
when (ccVerbose config) $
putStrLn "OK"
let wrapper :: IO a -> IO a
wrapper act = do
complexWrapper act
case cmd of
VanillaCmd -> wrapper vanillaRun
PolyCmd -> polyRun wrapper
```
```
$ ghc -c Main.hs
Main.hs:42:27: error: [GHC-25897]
• Couldn't match type ‘a’ with ‘()’
Expected: IO a -> IO a
Actual: IO () -> IO ()
‘a’ is a rigid type variable bound by
a type expected by the context:
forall a. IO a -> IO a
at Main.hs:42:27-33
• In the first argument of ‘polyRun’, namely ‘wrapper’
In the expression: polyRun wrapper
In a case alternative: PolyCmd -> polyRun wrapper
|
42 | PolyCmd -> polyRun wrapper
| ^^^^^^^
```
However this one does typecheck
```haskell
{-# LANGUAGE ApplicativeDo #-}
module Main (main) where
import Control.Monad
data Command
= PolyCmd
| VanillaCmd
data CommonConfig = CommonConfig
{ ccVerbose :: Bool
}
parseCommandline :: IO (CommonConfig, Command)
parseCommandline = undefined
locateHelper :: FilePath -> IO (Maybe FilePath)
locateHelper = undefined
complexWrapper :: IO a -> IO a
complexWrapper = undefined
vanillaRun :: IO ()
vanillaRun = pure ()
polyRun :: (forall a. IO a -> IO a) -> IO ()
polyRun f = f $ pure ()
main :: IO ()
main = do
(config, cmd) <- parseCommandline
let wrapper :: IO a -> IO a
wrapper act = do
when (ccVerbose config) $
putStrLn "OK"
complexWrapper act
case cmd of
VanillaCmd -> wrapper vanillaRun
PolyCmd -> polyRun wrapper
```
Commenting out `ApplicativeDo` also makes the original program typecheck.
## Expected behavior
Original program typechecks successfully with `ApplicativeDo` extension enabled.
## Environment
* GHC version used: 9.6.2
Optional:
* Operating System: Linux
* System Architecture: x86_64https://gitlab.haskell.org/ghc/ghc/-/issues/22899type-checking regression in 9.6.1-alpha2 - interaction between ApplicativeDo ...2023-02-07T16:33:08ZGanesh Sittampalamtype-checking regression in 9.6.1-alpha2 - interaction between ApplicativeDo and polymorphic arguments?## Summary
There's a compilation regression between GHC 9.4.3 and GHC 9.6.1-alpha2 which seems to be some interaction between `ApplicativeDo` and polymorphic arguments.
Cut down example below, which compiles in GHC 9.4.3 but fails in 9...## Summary
There's a compilation regression between GHC 9.4.3 and GHC 9.6.1-alpha2 which seems to be some interaction between `ApplicativeDo` and polymorphic arguments.
Cut down example below, which compiles in GHC 9.4.3 but fails in 9.6. It compiles fine in GHC 9.6 if I do any of:
- remove `ApplicativeDo`
- reorder the first two statements in the `do`
- remove the `pure ()`
- inline `go`.
It may be related to the `ApplicativeDo` desugaring itself as I've tried and failed to reproduce the regression with manually desugaring. I also later ran into another example of a regression in an applicative do block, this time with implicit parameters, that was also fixed by reorganising the code; I can also turn that into a test case if wanted.
Now that I understand the triggers I can probably work around it fairly easily in my real code, but I thought it may still be worth investigating as I can't spot any mention in [the migration guide](https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.6) or other issues.
## Steps to reproduce
```
{-# LANGUAGE ApplicativeDo #-}
module X where
x :: Maybe ()
x = do
pure ()
let go = Nothing
f go
f :: (forall p . Maybe p) -> Maybe ()
f _ = Nothing
```
With GHC 9.4.3 this compiles fine.
With GHC 9.6.0-alpha2 I get:
```
X.hs:8:5: error: [GHC-46956]
• Couldn't match type ‘a0’ with ‘p’
Expected: Maybe p
Actual: Maybe a0
because type variable ‘p’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
forall p. Maybe p
at X.hs:8:5-6
• In the first argument of ‘f’, namely ‘go’
In a stmt of a 'do' block: f go
In the expression:
do pure ()
let go = Nothing
f go
• Relevant bindings include go :: Maybe a0 (bound at X.hs:7:7)
|
8 | f go
| ^^
```
## Expected behavior
I'm not sure. Maybe it should work in GHC 9.6? Maybe my code is wrong and I just get lucky with earlier GHCs?
## Environment
* GHC version used: 9.6.1-alpha2sheafsam.derbyshire@gmail.comsheafsam.derbyshire@gmail.comhttps://gitlab.haskell.org/ghc/ghc/-/issues/22483ApplicativeDo causes the wrong line to be reported in non-exhaustive pattern ...2023-02-07T13:18:21ZJade LovelaceApplicativeDo causes the wrong line to be reported in non-exhaustive pattern error messages## Summary
With `ApplicativeDo` on, some programs (such as a test that crashed yesterday) that are Applicative in structure can get desugared to Applicative, and the source of non-exhaustive pattern error messages gets mixed up.
## Ste...## Summary
With `ApplicativeDo` on, some programs (such as a test that crashed yesterday) that are Applicative in structure can get desugared to Applicative, and the source of non-exhaustive pattern error messages gets mixed up.
## Steps to reproduce
Save this in `Test.hs`:
```haskell
main = do
let x = ()
res2 <- pure ()
~(Just res1) <- seq x (pure $ Nothing @())
print res1
print res2
pure ()
```
Then:
```
[nix-shell:~/dev/nixpkgs]$ runhaskell Test.hs
Test.hs: Test.hs:4:3-44: Non-exhaustive patterns in Just res1
[nix-shell:~/dev/nixpkgs]$ runhaskell -XApplicativeDo Test.hs
Test.hs: Test.hs:2:3-12: Non-exhaustive patterns in Just res1
```
Line 2 is incorrectly reported as the cause in the case of ApplicativeDo (which in the case of the test I was hacking on, was actually another irrefutable pattern that was actually fine, so I was absolutely baffled).
## Expected behavior
Both cases of `-XApplicativeDo` and not should report the same error location.
## Environment
* GHC version used: 9.4.3
Optional:
* Operating System: macOS
* System Architecture: aarch64Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/20630ApplicativeDo breaks uses of ImplicitParameters2022-08-15T16:04:37ZKhudyakovApplicativeDo breaks uses of ImplicitParameters## Summary
## Steps to reproduce
Following programs stops compiling if ApplicativeDo is enabled.
```haskell
-- {-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE ImplicitParams #-}
module Implicit where
implicit1, implicit2 :: (?ctx :: In...## Summary
## Steps to reproduce
Following programs stops compiling if ApplicativeDo is enabled.
```haskell
-- {-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE ImplicitParams #-}
module Implicit where
implicit1, implicit2 :: (?ctx :: Int) => IO Int
implicit1 = pure ?ctx
implicit2 = pure ?ctx
body :: IO Int
body = do
let ?ctx = 12 :: Int
x <- implicit1
y <- implicit2
pure $ x + y
```
with following error
```
/home/alexey/qqq/vector/implicit-do.hs:13:8: error:
• Unbound implicit parameter (?ctx::Int)
arising from a use of ‘implicit2’
• In a stmt of a 'do' block: y <- implicit2
In the expression: <<... snip ...>>
In an equation for ‘body’: <<... snip ...>>
```
Presumably this is because GHC desugars do-block using applicatives and this messes up scope of implicits.
## Expected behavior
I think that `?ctx` should be visible over rest of do block.
In program where this issue arose I tried to enable applicative do and it broke another function which happened to bind implicit parameters in do block.
## Environment
* GHC version used: 8.10.4, 9.2.0.202108219.4.3sheafsam.derbyshire@gmail.comsheafsam.derbyshire@gmail.comhttps://gitlab.haskell.org/ghc/ghc/-/issues/20540ApplicativeDo: `return` sometimes not allowed2022-12-19T02:30:02ZZiyang Liuunsafefixio@gmail.comApplicativeDo: `return` sometimes not allowed## Steps to reproduce
The following program is rejected, because "No instance for (Monad F) arising from a use of ‘return’".
```haskell
-- F is an Applicative but not a Monad
x :: F Int
x = do
let a = 3
return a
```
However, it is...## Steps to reproduce
The following program is rejected, because "No instance for (Monad F) arising from a use of ‘return’".
```haskell
-- F is an Applicative but not a Monad
x :: F Int
x = do
let a = 3
return a
```
However, it is accepted if `let a = 3` is changed to `a <- pure 3`.
## Expected behavior
In an ado-block, the last statement can be `return`, so the above program should be accepted.
## Environment
* GHC version used: 9.3.20210913Ziyang Liuunsafefixio@gmail.comZiyang Liuunsafefixio@gmail.comhttps://gitlab.haskell.org/ghc/ghc/-/issues/18816ApplicativeDo requires (>>=) and (<*>)2020-10-07T14:01:55ZKrzysztof GogolewskiApplicativeDo requires (>>=) and (<*>)The following ApplicativeDo+RebindableSyntax program requires `(>>=)` and `(<*>)` to be present in scope, even though neither is used. There's a similar problem with `return`, covered by #18313.
```
{-# LANGUAGE ApplicativeDo #-}
{-# LA...The following ApplicativeDo+RebindableSyntax program requires `(>>=)` and `(<*>)` to be present in scope, even though neither is used. There's a similar problem with `return`, covered by #18313.
```
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE RebindableSyntax #-}
module Bug where
import Prelude (Applicative(pure), Functor(..))
return x = [x]
(>>=) = (>>=) -- shouldn't be needed
(<*>) = (<*>) -- shouldn't be needed
xs :: [a]
xs = do
x <- []
pure x
```
Similar issue arises from combining ApplicativeDo+QualifiedDo:
```
module Ado where
(>>=) = undefined -- shouldn't be needed
(<*>) = undefined -- shouldn't be needed
pure :: Applicative f => a -> f a
pure = undefined
return :: Applicative f => a -> f a
return = Prelude.pure
fmap :: Functor f => (a -> b) -> f a -> f b
fmap = Prelude.fmap
----
{-# LANGUAGE QualifiedDo #-}
{-# LANGUAGE ApplicativeDo #-}
module Adotry where
import qualified Ado as A
xs :: [Int]
xs = A.do
x <- []
A.pure $ x
```
Bug found by Georgi Lyubenov https://twitter.com/aspiwack/status/1313595873058750464https://gitlab.haskell.org/ghc/ghc/-/issues/18559Let statements don't work with ApplicativeDo2022-07-16T21:59:58Zlennart@augustsson.netLet statements don't work with ApplicativeDo## Summary
Let statements don't work with ApplicativeDo.
Bug or feature?
## Steps to reproduce
Compile this snippet and see the compiler complain.
```
{-# LANGUAGE ApplicativeDo #-}
module Bug where
foo :: Applicative f => f Int
foo...## Summary
Let statements don't work with ApplicativeDo.
Bug or feature?
## Steps to reproduce
Compile this snippet and see the compiler complain.
```
{-# LANGUAGE ApplicativeDo #-}
module Bug where
foo :: Applicative f => f Int
foo = undefined
bar :: Applicative f => f Int
bar = do
x <- foo
let y = x + 1
pure y
```
## Expected behavior
I would expect `let` bound variables to be allowed if they are not used in any RHSs of `<-` bindings.
The example above can trivially bee rewritten to (which works)
```
bar :: Applicative f => f Int
bar = do
x <- foo
pure $ let y = x + 1 in y
```
## Environment
* GHC version used:
The Glorious Glasgow Haskell Compilation System, version 8.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/17971ApplicativeDo requires Monad constraint in recursive definition2020-04-08T23:34:18ZManuel BärenzApplicativeDo requires Monad constraint in recursive definition## Summary
With some kinds of recursion, and `ApplicativeDo` enabled, a Monad constraint is required, even though `Applicative` would have been sufficient.
## Steps to reproduce
Typecheck this:
```haskell
foreverA :: Applicative f =>...## Summary
With some kinds of recursion, and `ApplicativeDo` enabled, a Monad constraint is required, even though `Applicative` would have been sufficient.
## Steps to reproduce
Typecheck this:
```haskell
foreverA :: Applicative f => f a -> f b
foreverA fa = do
_a <- fa
foreverA fa
```
The error message is:
```
Main.hs:10:3: error:
• Could not deduce (Monad f) arising from a do statement
from the context: Applicative f
bound by the type signature for:
foreverA :: forall (f :: * -> *) a. Applicative f => f a -> f ()
at Main.hs:8:1-40
Possible fix:
add (Monad f) to the context of
the type signature for:
foreverA :: forall (f :: * -> *) a. Applicative f => f a -> f ()
• In a stmt of a 'do' block: _a <- fa
In the expression:
do _a <- fa
foreverA fa
In an equation for ‘foreverA’:
foreverA fa
= do _a <- fa
foreverA fa
|
10 | _a <- fa
| ^^^^^^^^
```
This can be worked around by adding `pure ()` as a last line, as pointed out by `maerwald` on IRC.
For a more involved example that doesn't have this kind of fix, consider:
```haskell
{-# LANGUAGE ApplicativeDo #-}
module StreamT where
-- base
import Control.Arrow
data StreamT m a = StreamT { unStreamT :: m (a, StreamT m a) }
instance Functor m => Functor (StreamT m) where
fmap f = StreamT . fmap (f *** fmap f) . unStreamT
instance Applicative m => Applicative (StreamT m) where
pure a = StreamT $ pure (a, pure a)
fs <*> as = StreamT $ do
(f, fs') <- unStreamT fs
(a, as') <- unStreamT as
pure (f a, fs' <*> as')
```
Error message:
```
Main.hs:22:5: error:
• Could not deduce (Monad m) arising from a do statement
from the context: Applicative m
bound by the instance declaration at Main.hs:19:10-49
Possible fix:
add (Monad m) to the context of
the type signature for:
(<*>) :: forall a b.
StreamT m (a -> b) -> StreamT m a -> StreamT m b
or the instance declaration
• In a stmt of a 'do' block: (f, fs') <- unStreamT fs
In the second argument of ‘($)’, namely
‘do (f, fs') <- unStreamT fs
(a, as') <- unStreamT as
pure (f a, fs' <*> as')’
In the expression:
StreamT
$ do (f, fs') <- unStreamT fs
(a, as') <- unStreamT as
pure (f a, fs' <*> as')
|
22 | (f, fs') <- unStreamT fs
| ^^^^^^^^^^^^^^^^^^^^^^^^
```
## Expected behavior
`ApplicativeDo` can correctly desugar this recursive definition.
## Environment
* GHC version used: 8.8
Optional:
* Operating System: NixOS (Linux)https://gitlab.haskell.org/ghc/ghc/-/issues/17835Regression with ApplicativeDo in 8.10-rc12020-04-08T07:45:03ZadamRegression with ApplicativeDo in 8.10-rc1This program fails to compile in GHC 8.10-rc1:
```haskell
-- Build.hs
{-# LANGUAGE ApplicativeDo #-}
module Build (configRules) where
type Action = IO
type Rules = IO
type Config = ()
(%>) :: String -> (String -> Action ()) -> Rules ...This program fails to compile in GHC 8.10-rc1:
```haskell
-- Build.hs
{-# LANGUAGE ApplicativeDo #-}
module Build (configRules) where
type Action = IO
type Rules = IO
type Config = ()
(%>) :: String -> (String -> Action ()) -> Rules ()
(%>) = undefined
command_ :: [String] -> String -> [String] -> Action ()
command_ = undefined
recursive :: Config -> String -> [String] -> IO (FilePath, [String])
recursive = undefined
liftIO :: IO a -> Action a
liftIO = id
need :: [String] -> Action ()
need = undefined
historyDisable :: Action ()
historyDisable = undefined
get_config :: () -> Action Config
get_config = undefined
configRules :: Rules ()
configRules = do
"snapshot" %> \out -> do
historyDisable -- 8.10-rc1 refuses to compile without bind here
config <- get_config ()
need []
(exe,args) <- liftIO $ recursive config "snapshot" []
command_ [] exe args
```
```
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.10.0.20200123
$ ghc -c Build.hs -fforce-recomp
Build.hs:38:5: error:
• Couldn't match expected type ‘IO ([String], String)’
with actual type ‘([String], FilePath)’
• In the expression:
do historyDisable
config <- get_config ()
need []
(exe, args) <- liftIO $ recursive config "snapshot" []
command_ [] exe args
In the second argument of ‘(%>)’, namely
‘\ out
-> do historyDisable
config <- get_config ()
need []
(exe, args) <- liftIO $ recursive config "snapshot" []
command_ [] exe args’
In a stmt of a 'do' block:
"snapshot"
%>
\ out
-> do historyDisable
config <- get_config ()
need []
(exe, args) <- liftIO $ recursive config "snapshot" []
command_ [] exe args
|
38 | config <- get_config ()
| ^^^^^^
```
If I instead write `() <- historyDisable` compilation works.8.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/17170ApplicativeDo should use a more accurate cost model2020-01-23T19:48:51ZSophie TaylorApplicativeDo should use a more accurate cost model## Motivation
It currently assumes that each statement has the same cost. This is fine if each statement actually DOES have a similar cost, but there is already a much more sophisticated cost model in GHC.
## Proposal
Two independent a...## Motivation
It currently assumes that each statement has the same cost. This is fine if each statement actually DOES have a similar cost, but there is already a much more sophisticated cost model in GHC.
## Proposal
Two independent approaches seem useful.
1. The cost could be computed using the cost model the inliner uses. While it is not perfect, either, it is likely to be more accurate overall than the current situation.
2. Annotations could be provided to document the "effect cost" of an effectful function. For example, in a logging effect which has three operations - appending to a buffer, appending to a file, and sending a message over a network connection - could have different costs manually annotated.https://gitlab.haskell.org/ghc/ghc/-/issues/16628GHC doesn't catch missing MonadFail constraint with -XApplicativeDo2019-10-28T13:37:31ZSimon JakobiGHC doesn't catch missing MonadFail constraint with -XApplicativeDo```
-- Bug.hs
module Main where
import Data.Functor.Identity
f :: Identity () -> Identity [Int] -> Identity Int
f i0 i1 = do
_ <- i0
[x] <- i1
pure (x + 42)
main :: IO ()
main = print $ f (Identity ()) (Identity [])
```
With `-...```
-- Bug.hs
module Main where
import Data.Functor.Identity
f :: Identity () -> Identity [Int] -> Identity Int
f i0 i1 = do
_ <- i0
[x] <- i1
pure (x + 42)
main :: IO ()
main = print $ f (Identity ()) (Identity [])
```
With `-XApplicativeDo`, GHC compiles this program without error or warning. But the resulting program fails at runtime:
```
$ ghc-8.8.1 -XApplicativeDo --make Bug.hs
[1 of 1] Compiling Main ( Bug.hs, Bug.o )
Linking Bug ...
$ ./Bug
Bug: Bug.hs:(6,11)-(9,15): Non-exhaustive patterns in lambda
```
Only when the `-XApplicativeDo` option is removed does GHC catch the missing constraint:
```
$ ghc-8.8.1 --make Bug.hs
[1 of 1] Compiling Main ( Bug.hs, Bug.o ) [flags changed]
Bug.hs:8:3: error:
• No instance for (MonadFail Identity)
arising from a do statement
with the failable pattern ‘[x]’
• In a stmt of a 'do' block: [x] <- i1
In the expression:
do _ <- i0
[x] <- i1
pure (x + 42)
In an equation for ‘f’:
f i0 i1
= do _ <- i0
[x] <- i1
pure (x + 42)
|
8 | [x] <- i1
| ^^^^^^^^^
```
A variation of the problematic program had been reported in https://gitlab.haskell.org/ghc/ghc/issues/15344.8.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/16171"ApplicativeDo" disables -Wunused-do-binds?2023-03-31T13:19:35ZErik Schnetter"ApplicativeDo" disables -Wunused-do-binds?In the code below, the return value of `forkIO` is ignored. The compiler does not warn about this. When I disable the `ApplicativeDo` extension, the warning appears as expected.
```
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE ApplicativeDo #...In the code below, the return value of `forkIO` is ignored. The compiler does not warn about this. When I disable the `ApplicativeDo` extension, the warning appears as expected.
```
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE ApplicativeDo #-}
module Example (main) where
import Control.Concurrent
main :: IO ()
main = do x <- return ()
forkIO (putStrLn "hello")
putStrLn $ "world" ++ show x
```https://gitlab.haskell.org/ghc/ghc/-/issues/16135Assertion failure with ExistentialQuantification and ApplicativeDo2024-03-28T05:02:38ZAshley YakeleyAssertion failure with ExistentialQuantification and ApplicativeDo```hs
{-# LANGUAGE ExistentialQuantification, ApplicativeDo #-}
module Bug where
data T f = forall a. MkT (f a)
runf :: forall f. Functor f => IO (T f)
runf = do
return ()
MkT fa <- runf
return $ MkT fa
```
```
Bug.hs:11:...```hs
{-# LANGUAGE ExistentialQuantification, ApplicativeDo #-}
module Bug where
data T f = forall a. MkT (f a)
runf :: forall f. Functor f => IO (T f)
runf = do
return ()
MkT fa <- runf
return $ MkT fa
```
```
Bug.hs:11:18: error:ghc: panic! (the 'impossible' happened)
(GHC version 8.6.3 for x86_64-unknown-linux):
No skolem info:
[a_a1nb[ssk:2]]
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler/utils/Outputable.hs:1160:37 in ghc:Outputable
pprPanic, called at compiler/typecheck/TcErrors.hs:2891:5 in ghc:TcErrors
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
```https://gitlab.haskell.org/ghc/ghc/-/issues/15422GHCi debugger doesn't see free variables when using ApplicativeDo2019-07-07T18:04:58ZSimon MarlowGHCi debugger doesn't see free variables when using ApplicativeDo```
> ghci break029.hs
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( break029.hs, interpreted )
Ok, one module loaded.
*Main> :!cat break029.hs
{-# LANGUAGE ApplicativeDo #-}
f :: In...```
> ghci break029.hs
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( break029.hs, interpreted )
Ok, one module loaded.
*Main> :!cat break029.hs
{-# LANGUAGE ApplicativeDo #-}
f :: Int -> IO Int
f x = do
y <- return (x + 1)
return (y * 2)
*Main> :step f 3
Stopped in Main.f, break029.hs:(4,7)-(6,16)
_result :: IO Int = _
x :: Int = 3
[break029.hs:(4,7)-(6,16)] [break029.hs:(4,7)-(6,16)] *Main> :list
3 f :: Int -> IO Int
4 f x = do
5 y <- return (x + 1)
6 return (y * 2)
7
[break029.hs:(4,7)-(6,16)] [break029.hs:(4,7)-(6,16)] *Main> :step
Stopped in Main.f, break029.hs:5:8-21
_result :: IO Int = _
x :: Int = 3
[break029.hs:5:8-21] [break029.hs:5:8-21] *Main> :list
4 f x = do
5 y <- return (x + 1)
6 return (y * 2)
[break029.hs:5:8-21] [break029.hs:5:8-21] *Main> :step
Stopped in Main.f, break029.hs:6:11-15
_result :: Int = _
[break029.hs:6:11-15] [break029.hs:6:11-15] *Main> y
<interactive>:7:1: error: Variable not in scope: y
```8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15344ApplicativeDo seems to prevent the fail method from being used2020-04-08T07:45:03ZkccqzyApplicativeDo seems to prevent the fail method from being usedI am not sure if this is intended, but I came across this issue when debugging a runtime exception. It seems like an incomplete pattern match in a do-block with ApplicativeDo enabled will not use the fail method.
If I have a module like...I am not sure if this is intended, but I came across this issue when debugging a runtime exception. It seems like an incomplete pattern match in a do-block with ApplicativeDo enabled will not use the fail method.
If I have a module like this
```hs
{-# LANGUAGE ApplicativeDo #-}
{-# OPTIONS_ghc -ddump-simpl #-}
module M where
f :: Maybe (Maybe Int) -> Maybe Int -> Maybe Int
f mgs mid = do
_ <- mid
(Just moi) <- mgs
pure (moi + 42)
main :: IO ()
main = print (f (Just Nothing) (Just 2))
```
This will result in a runtime exception:
```
Just *** Exception: repro.hs:(6,13)-(9,17): Non-exhaustive patterns in lambda
```
But if I remove the ApplicativeDo extension, this code works as normal, producing Nothing as the output.
On a theoretical level I understand why this is happening, but I still find it quite unexpected, especially since the documentation at https://downloads.haskell.org/\~ghc/latest/docs/html/users_guide/glasgow_exts.html\#things-to-watch-out-for claims that
> Your code should just work as before when ApplicativeDo is enabled, provided you use conventional Applicative instances.
If this is not a defect in GHC itself, I'd say it is a defect in documentation in not pointing out this gotcha.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"ApplicativeDo seems to prevent the fail method from being used","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"I am not sure if this is intended, but I came across this issue when debugging a runtime exception. It seems like an incomplete pattern match in a do-block with ApplicativeDo enabled will not use the fail method.\r\n\r\nIf I have a module like this\r\n\r\n{{{#!hs\r\n{-# LANGUAGE ApplicativeDo #-}\r\n{-# OPTIONS_ghc -ddump-simpl #-}\r\nmodule M where\r\n\r\nf :: Maybe (Maybe Int) -> Maybe Int -> Maybe Int\r\nf mgs mid = do\r\n _ <- mid\r\n (Just moi) <- mgs\r\n pure (moi + 42)\r\n\r\nmain :: IO ()\r\nmain = print (f (Just Nothing) (Just 2))\r\n\r\n}}}\r\n\r\nThis will result in a runtime exception:\r\n\r\n{{{\r\nJust *** Exception: repro.hs:(6,13)-(9,17): Non-exhaustive patterns in lambda\r\n}}}\r\n\r\nBut if I remove the ApplicativeDo extension, this code works as normal, producing Nothing as the output.\r\n\r\nOn a theoretical level I understand why this is happening, but I still find it quite unexpected, especially since the documentation at https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#things-to-watch-out-for claims that \r\n\r\n> Your code should just work as before when ApplicativeDo is enabled, provided you use conventional Applicative instances.\r\n\r\nIf this is not a defect in GHC itself, I'd say it is a defect in documentation in not pointing out this gotcha.","type_of_failure":"OtherFailure","blocking":[]} -->8.10.1