GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2021-11-09T15:32:18Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/10976Applicative Comprehensions2021-11-09T15:32:18ZdavidarApplicative ComprehensionsAs discussed on [ghc-devs](https://mail.haskell.org/pipermail/ghc-devs/2015-October/010062.html), when both the `MonadComprehensions` and `ApplicativeDo` language extensions are enabled, it should be possible to use comprehension-notatio...As discussed on [ghc-devs](https://mail.haskell.org/pipermail/ghc-devs/2015-October/010062.html), when both the `MonadComprehensions` and `ApplicativeDo` language extensions are enabled, it should be possible to use comprehension-notation (in addition to do-notation) for `Applicative`s. This would allow, for example, an expression like
```hs
(\x y -> x + 2*y) <$> ZipList [1..10] <*> ZipList [10,20..100]
```
to also be written as
```hs
[ x + 2*y | x <- ZipList [1..10], y <- ZipList [10,20..100] ]
```8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/15016Referencing a do-bound variable in a rec block with ApplicativeDo results in ...2021-08-06T00:14:44ZrjmkReferencing a do-bound variable in a rec block with ApplicativeDo results in variable not in scope during type checkingI searched + hope this isn't a dupe.
When using both ApplicativeDo and RecursiveDo, referring to a do-bound variable from outside of a rec block causes a GHC internal error.
Here's a minimal example:
```hs
{-# LANGUAGE ApplicativeDo #...I searched + hope this isn't a dupe.
When using both ApplicativeDo and RecursiveDo, referring to a do-bound variable from outside of a rec block causes a GHC internal error.
Here's a minimal example:
```hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE RecursiveDo #-}
module Lib where
import Control.Monad.Fix
f :: MonadFix m => m ()
f = do
a <- return ()
rec
let b = a
return ()
```
The error message I get is
```
src/Lib.hs:12:13: error:
• GHC internal error: ‘a’ is not in scope during type checking, but it passed the renamer
tcl_env of environment: [a1pF :-> Type variable ‘m’ = m :: * -> *,
r1mX :-> Identifier[f::forall (m :: * -> *).
MonadFix m =>
m (), TopLevelLet [] True]]
• In the expression: a
In an equation for ‘b’: b = a
In a stmt of a 'do' block: rec let b = a
|
12 | let b = a
| ^
```
I have reproduced it in 8.2.2 and 8.4.1
<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":"Referencing a do-bound variable in a rec block with ApplicativeDo results in variable not in scope during type checking","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.4.3","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"I searched + hope this isn't a dupe.\r\n\r\nWhen using both ApplicativeDo and RecursiveDo, referring to a do-bound variable from outside of a rec block causes a GHC internal error.\r\n\r\nHere's a minimal example:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE ApplicativeDo #-}\r\n{-# LANGUAGE RecursiveDo #-}\r\n\r\nmodule Lib where\r\n\r\nimport Control.Monad.Fix\r\n\r\nf :: MonadFix m => m ()\r\nf = do\r\n a <- return ()\r\n rec\r\n let b = a\r\n return ()\r\n}}}\r\n\r\nThe error message I get is\r\n\r\n\r\n{{{\r\nsrc/Lib.hs:12:13: error:\r\n • GHC internal error: ‘a’ is not in scope during type checking, but it passed the renamer\r\n tcl_env of environment: [a1pF :-> Type variable ‘m’ = m :: * -> *,\r\n r1mX :-> Identifier[f::forall (m :: * -> *).\r\n MonadFix m =>\r\n m (), TopLevelLet [] True]]\r\n • In the expression: a\r\n In an equation for ‘b’: b = a\r\n In a stmt of a 'do' block: rec let b = a\r\n |\r\n12 | let b = a\r\n | ^\r\n}}}\r\n\r\n\r\nI have reproduced it in 8.2.2 and 8.4.1\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.4.3Simon MarlowSimon Marlowhttps://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/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/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/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/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/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/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/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/15100`ApplicativeDo` needlessly uses `join` too much2020-01-23T19:20:59ZEdward Kmett`ApplicativeDo` needlessly uses `join` too much```hs
foo = do
A 1
B 2
C 3
return ()
```
produces very different code than
```hs
foo = do
A 1
B 2
C 3
```
for no good reason. Currently we check to see if the last clause is a `return` or something else, and then bolt a...```hs
foo = do
A 1
B 2
C 3
return ()
```
produces very different code than
```hs
foo = do
A 1
B 2
C 3
```
for no good reason. Currently we check to see if the last clause is a `return` or something else, and then bolt a `join` in if it isn't `return`. But this check is too conservative. If it isn't a `return` but doesn't reference any of the variables above, you can still desugar it with `(<*>)`.
We found this during a twitch livestream in front of an audience of 127 people. =)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------ |
| Version | 8.4.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (CodeGen) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"`ApplicativeDo` needlessly uses `join` too much","status":"New","operating_system":"","component":"Compiler (CodeGen)","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{#!hs\r\nfoo = do\r\n A 1\r\n B 2\r\n C 3\r\n return () \r\n}}}\r\n\r\nproduces very different code than\r\n\r\n{{{#!hs\r\nfoo = do\r\n A 1\r\n B 2\r\n C 3\r\n}}}\r\n\r\nfor no good reason. Currently we check to see if the last clause is a `return` or something else, and then bolt a `join` in if it isn't `return`. But this check is too conservative. If it isn't a `return` but doesn't reference any of the variables above, you can still desugar it with `(<*>)`. \r\n\r\nWe found this during a twitch livestream in front of an audience of 127 people. =)","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14700ApplicativeDo in MonadComprehensions2020-08-21T17:05:31ZlspitznerApplicativeDo in MonadComprehensionsIt appears that a MonadComp (even one that is "Applicative only") is not transformed appropriately in the presence of ApplicativeDo.
```hs
{-# LANGUAGE MonadComprehensions #-}
{-# LANGUAGE ApplicativeDo #-}
value1 = [ f a b c | a <- ma...It appears that a MonadComp (even one that is "Applicative only") is not transformed appropriately in the presence of ApplicativeDo.
```hs
{-# LANGUAGE MonadComprehensions #-}
{-# LANGUAGE ApplicativeDo #-}
value1 = [ f a b c | a <- ma, b <- mb, c <- mc ]
value2 = do { a <- ma; b <- mb; c <- mc; return (f a b c) }
value3 = f <$> ma <*> mb <*> mc
```
value1 should desugar to value2 via monadcomp and to value3 via appdo. Yet I observe very bad performance in some specific instance (due to a slower Monad instance) when using value1, where value2 and value3 have good performance. I have not looked at desuraged/core dumps but the observation seems clear.
Tested on ghc-8.0.2 only.
<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 in MonadComprehensions","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":"It appears that a MonadComp (even one that is \"Applicative only\") is not transformed appropriately in the presence of ApplicativeDo.\r\n\r\n{{{#!hs\r\n{-# LANGUAGE MonadComprehensions #-}\r\n{-# LANGUAGE ApplicativeDo #-}\r\n\r\nvalue1 = [ f a b c | a <- ma, b <- mb, c <- mc ]\r\nvalue2 = do { a <- ma; b <- mb; c <- mc; return (f a b c) }\r\nvalue3 = f <$> ma <*> mb <*> mc\r\n}}}\r\n\r\nvalue1 should desugar to value2 via monadcomp and to value3 via appdo. Yet I observe very bad performance in some specific instance (due to a slower Monad instance) when using value1, where value2 and value3 have good performance. I have not looked at desuraged/core dumps but the observation seems clear.\r\n\r\nTested on ghc-8.0.2 only.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14252ApplicativeDo: Add compiler message about irrefutable pattern matches and Mon...2020-01-23T19:27:39ZmutantmellApplicativeDo: Add compiler message about irrefutable pattern matches and Monad constraintsAdd an error message to the compiler when:
- A user-provided signature specifies a Functor/Applicative constraint
- ApplicativeDo desugaring requires a Monad constraint
- Adding a lazy pattern match could allow the Functor/Applicative c...Add an error message to the compiler when:
- A user-provided signature specifies a Functor/Applicative constraint
- ApplicativeDo desugaring requires a Monad constraint
- Adding a lazy pattern match could allow the Functor/Applicative constraint
bgamari suggests something like the following message:
```
ApplicativeDo is enabled yet Monad is required due to irrefutable pattern match;
perhaps you want to make the match refutable by adding a ~?
```
Background:
In GHC 8.2.1, ApplicativeDo desugaring was changed to require monad constraints when using a strict pattern match (see #13875 for details). While this behavior is a requirement for maintaining the intended semantics of ApplicativeDo, it is both a breaking change, and somewhat unintuitive (see #14249). Adding a message would provide both clarification around the requirement, and provide a simple resolution for the common use case.https://gitlab.haskell.org/ghc/ghc/-/issues/13906ApplicativeDo doesn't handle existentials as well as it could2020-01-23T19:31:02ZDavid FeuerApplicativeDo doesn't handle existentials as well as it could`ApplicativeDo` doesn't work nicely with existentials or GADTs. This was first considered in #13242, but I think it's worth reconsidering in light of #13875. In particular, we no longer need to think specially about whether a particular ...`ApplicativeDo` doesn't work nicely with existentials or GADTs. This was first considered in #13242, but I think it's worth reconsidering in light of #13875. In particular, we no longer need to think specially about whether a particular pattern match reveals evidence, as any pattern match that does so must necessarily be strict. Simon Marlow explains (in revised, I-think-unmerged, documentation) that
```hs
data T where A :: forall a . Eq a => a -> T
test = do
A x <- undefined
_ <- return 'a'
_ <- return 'b'
return (x == x)
```
will not typecheck because it is first rearranged to
```hs
test =
(\x _ -> x == x)
<$> do A x <- undefined; _ <- return 'a'; return x
<*> return 'b'
```
This is weird! The more human-obvious rearrangement would work just fine:
```hs
test = do
A x <- undefined
(\_ _ -> x == x) <$> return 'a' <*> return 'b'
```
How can we get there? I think it's actually easy. Suppose we have
```hs
do
p1 <- e1
p2 <- e2
p3 <- e3
p4 <- e4
p5 <- e5
e6
```
Before starting the detailed dependency analysis and such, let's look just at *which patterns are strict*. If a pattern is strict, then *every* following action must be seen as depending on it, and therefore its bindings and evidence can scope over everything else. Let's say that `p3` is strict. Then we can immediately transform the expression to
```hs
do
p1 <- e1
p2 <- e2
e3 >>= \case
p3 -> do
p4 <- e4
p5 <- e5
e6
-- if refutable
_ -> fail ...
```
and then continue the process in the inner `do` block.
If this is done as an initial pass, then further rearrangement doesn't need to consider the possibility of strict patterns; there won't be any.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"ApplicativeDo doesn't handle existentials as well as it could","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.4.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":["ApplicativeDo"],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"Bug","description":"`ApplicativeDo` doesn't work nicely with existentials or GADTs. This was first considered in #13242, but I think it's worth reconsidering in light of #13875. In particular, we no longer need to think specially about whether a particular pattern match reveals evidence, as any pattern match that does so must necessarily be strict. Simon Marlow explains (in revised, I-think-unmerged, documentation) that\r\n\r\n{{{#!hs\r\n data T where A :: forall a . Eq a => a -> T\r\n\r\n test = do\r\n A x <- undefined\r\n _ <- return 'a'\r\n _ <- return 'b'\r\n return (x == x)\r\n}}}\r\n\r\nwill not typecheck because it is first rearranged to\r\n\r\n{{{#!hs\r\n test =\r\n (\\x _ -> x == x)\r\n <$> do A x <- undefined; _ <- return 'a'; return x\r\n <*> return 'b'\r\n}}}\r\n\r\nThis is weird! The more human-obvious rearrangement would work just fine:\r\n\r\n{{{#!hs\r\n test = do\r\n A x <- undefined\r\n (\\_ _ -> x == x) <$> return 'a' <*> return 'b'\r\n}}}\r\n\r\nHow can we get there? I think it's actually easy. Suppose we have\r\n\r\n{{{#!hs\r\n do\r\n p1 <- e1\r\n p2 <- e2\r\n p3 <- e3\r\n p4 <- e4\r\n p5 <- e5\r\n e6\r\n}}}\r\n\r\nBefore starting the detailed dependency analysis and such, let's look just at ''which patterns are strict''. If a pattern is strict, then ''every'' following action must be seen as depending on it, and therefore its bindings and evidence can scope over everything else. Let's say that `p3` is strict. Then we can immediately transform the expression to\r\n\r\n{{{#!hs\r\n do\r\n p1 <- e1\r\n p2 <- e2\r\n e3 >>= \\case\r\n p3 -> do\r\n p4 <- e4\r\n p5 <- e5\r\n e6\r\n -- if refutable\r\n _ -> fail ...\r\n}}}\r\n\r\nand then continue the process in the inner `do` block.\r\n\r\nIf this is done as an initial pass, then further rearrangement doesn't need to consider the possibility of strict patterns; there won't be any.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13905ApplicativeDo is too strict with newtype patterns2020-01-23T19:31:02ZDavid FeuerApplicativeDo is too strict with newtype patternsThe fix to #13875 went a little too far, and interprets newtype constructor patterns as strict. It's not clear to me how to fix this, as the `Name` of the constructor doesn't seem to give any clue as to whether it is a newtype constructo...The fix to #13875 went a little too far, and interprets newtype constructor patterns as strict. It's not clear to me how to fix this, as the `Name` of the constructor doesn't seem to give any clue as to whether it is a newtype constructor or a data constructor. The comment at the top of `basicTypes/Name.hs` indicates
```
-- * 'Name.Name' is the type of names that have had their scoping and binding resolved. They
-- have an 'OccName.OccName' but also a 'Unique.Unique' that disambiguates Names that have
-- the same 'OccName.OccName' and indeed is used for all 'Name.Name' comparison. Names
-- also contain information about where they originated from, see "Name#name_sorts"
```
which suggests that this information should be available, but I don't know what's involved in propagating it to the right place.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"ApplicativeDo is too strict with newtype patterns","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.4.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"Bug","description":"The fix to #13875 went a little too far, and interprets newtype constructor patterns as strict. It's not clear to me how to fix this, as the `Name` of the constructor doesn't seem to give any clue as to whether it is a newtype constructor or a data constructor. The comment at the top of `basicTypes/Name.hs` indicates\r\n\r\n{{{\r\n-- * 'Name.Name' is the type of names that have had their scoping and binding resolved. They\r\n-- have an 'OccName.OccName' but also a 'Unique.Unique' that disambiguates Names that have\r\n-- the same 'OccName.OccName' and indeed is used for all 'Name.Name' comparison. Names\r\n-- also contain information about where they originated from, see \"Name#name_sorts\"\r\n}}}\r\n\r\nwhich suggests that this information should be available, but I don't know what's involved in propagating it to the right place.","type_of_failure":"OtherFailure","blocking":[]} -->