GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2020-01-23T19:37:51Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/10892ApplicativeDo should use *> and <*2020-01-23T19:37:51ZSimon MarlowApplicativeDo should use *> and <*From \@ekmett:
Would it be possible to tweak the generation to use `(<*)` or `(*>)` where appropriate when the result isn't being used?
For many Applicatives this can be a massive asymptotic win in terms of sharing and/or computational...From \@ekmett:
Would it be possible to tweak the generation to use `(<*)` or `(*>)` where appropriate when the result isn't being used?
For many Applicatives this can be a massive asymptotic win in terms of sharing and/or computational cost.
When desugaring using (\<\*) you'd just omit any handling of the unused result instead.
```
(\x y -> ...) <$> foo <* bar <*> baz
```
corresponds to
```
do x <- foo
bar
y <- baz
return ...
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.11 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | ekmett |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"ApplicativeDo should use *> and <*","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.0.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.11","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["ekmett"],"type":"Task","description":"From @ekmett:\r\n\r\nWould it be possible to tweak the generation to use `(<*)` or `(*>)` where appropriate when the result isn't being used?\r\n\r\nFor many Applicatives this can be a massive asymptotic win in terms of sharing and/or computational cost.\r\n\r\nWhen desugaring using (<*) you'd just omit any handling of the unused result instead.\r\n\r\n{{{\r\n(\\x y -> ...) <$> foo <* bar <*> baz\r\n}}}\r\n\r\ncorresponds to\r\n\r\n{{{\r\ndo x <- foo\r\n bar\r\n y <- baz\r\n return ...\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->SiddharthSiddharthhttps://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/11607ApplicativeDo easily foiled with `pure`2019-07-07T18:29:38ZBen GamariApplicativeDo easily foiled with `pure``ApplicativeDo` fails to desugar `do` blocks ending with `pure`. For instance,
```hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype MaybeA a = MaybeA (Maybe a)
deriving (Show, Functo...`ApplicativeDo` fails to desugar `do` blocks ending with `pure`. For instance,
```hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype MaybeA a = MaybeA (Maybe a)
deriving (Show, Functor, Applicative)
main = print $ do x <- MaybeA $ Just 42
pure x
```
However, if the final `pure` is changed to `return` things work as expected.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 8.0.1-rc2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | high |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"ApplicativeDo easily foiled with `pure`","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"8.0.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1-rc2","keywords":["ApplicativeDo"],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"Bug","description":"`ApplicativeDo` fails to desugar `do` blocks ending with `pure`. For instance,\r\n{{{#!hs\r\n{-# LANGUAGE ApplicativeDo #-}\r\n{-# LANGUAGE GeneralizedNewtypeDeriving #-}\r\n\r\nnewtype MaybeA a = MaybeA (Maybe a)\r\n deriving (Show, Functor, Applicative)\r\n\r\nmain = print $ do x <- MaybeA $ Just 42\r\n pure x\r\n}}}\r\n\r\nHowever, if the final `pure` is changed to `return` things work as expected.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Ben GamariBen Gamarihttps://gitlab.haskell.org/ghc/ghc/-/issues/11612Bug in ApplicativeDo2019-07-07T18:29:36ZSimon MarlowBug in ApplicativeDoI discovered a bug in `ApplicativeDo`. Fix coming shortly. The problem is illustrated by this test case, which I will add to `ado001.hs` in the testsuite:
```
test11 :: M ()
test11 = do
x1 <- a
let x2 = x1
x3 <- b
let x4 = c
...I discovered a bug in `ApplicativeDo`. Fix coming shortly. The problem is illustrated by this test case, which I will add to `ado001.hs` in the testsuite:
```
test11 :: M ()
test11 = do
x1 <- a
let x2 = x1
x3 <- b
let x4 = c
x5 = x4
return (const () (x1,x2,x3,x4))
```
Which should give `(a | b)`, but gives `(a ; b)` in 8.0.1 RC.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.10.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | high |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Bug in ApplicativeDo","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.0.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"I discovered a bug in `ApplicativeDo`. Fix coming shortly. The problem is illustrated by this test case, which I will add to `ado001.hs` in the testsuite:\r\n\r\n{{{\r\ntest11 :: M ()\r\ntest11 = do\r\n x1 <- a\r\n let x2 = x1\r\n x3 <- b\r\n let x4 = c\r\n x5 = x4\r\n return (const () (x1,x2,x3,x4))\r\n}}}\r\n\r\nWhich should give `(a | b)`, but gives `(a ; b)` in 8.0.1 RC.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/11835ApplicativeDo failed to desugar last line with pure $ <expr>2019-07-07T18:28:20ZCosmiaApplicativeDo failed to desugar last line with pure $ <expr>```hs
{-# LANGUAGE ApplicativeDo #-}
f m = do
x <- m 1
y <- m 2
return $ x + y
```
f should have type (Applicative f, Num a, Num b) =\> (a -\> f b) -\> f b
but ghc considers f a monad
maybe similar with #11607
<details><summary>...```hs
{-# LANGUAGE ApplicativeDo #-}
f m = do
x <- m 1
y <- m 2
return $ x + y
```
f should have type (Applicative f, Num a, Num b) =\> (a -\> f b) -\> f b
but ghc considers f a monad
maybe similar with #11607
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.1-rc2 |
| 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 failed to desugar last line with pure $ <expr>","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1-rc2","keywords":["ApplicativeDo"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{#!hs\r\n{-# LANGUAGE ApplicativeDo #-}\r\nf m = do\r\n x <- m 1\r\n y <- m 2\r\n return $ x + y\r\n}}}\r\nf should have type (Applicative f, Num a, Num b) => (a -> f b) -> f b\r\nbut ghc considers f a monad\r\n\r\nmaybe similar with #11607","type_of_failure":"OtherFailure","blocking":[]} -->8.0.2Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/11982Typechecking fails for parallel monad comprehensions with polymorphic let (GH...2019-07-07T18:28:09ZSimon Peyton JonesTypechecking fails for parallel monad comprehensions with polymorphic let (GHC 7.10.3 through 8.6.3)```
{-# LANGUAGE MonadComprehensions, ParallelListComp #-}
module Foo where
foo xs ys = [ (f y True, f x 'c')
| let f _ z = z, x <- xs
| y <- ys ]
```
This fails with
```
Foo.hs:5:52: error:
* Cannot insta...```
{-# LANGUAGE MonadComprehensions, ParallelListComp #-}
module Foo where
foo xs ys = [ (f y True, f x 'c')
| let f _ z = z, x <- xs
| y <- ys ]
```
This fails with
```
Foo.hs:5:52: error:
* Cannot instantiate unification variable `t0'
with a type involving foralls: forall t2 t3. t3 -> t2 -> t2
GHC doesn't yet support impredicative polymorphism
* In a stmt of a monad comprehension:
let f _ z = z, x <- xs | y <- ys
In the expression:
[(f y True, f x 'c') | let f _ z = z, x <- xs | y <- ys]
In an equation for `foo':
foo xs ys
= [(f y True, f x 'c') | let f _ z = z, x <- xs | y <- ys]
```
NB: `ApplicativeDo` has a related problem: the implementation is quite different and has the effect of monomorphising the let-bound variable.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.10.3 |
| 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":"Typechecking fails for parallel monad comprehensions with polymorphic let","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{\r\n{-# LANGUAGE MonadComprehensions, ParallelListComp #-}\r\n\r\nmodule Foo where\r\n\r\nfoo xs ys = [ (f y True, f x 'c')\r\n | let f _ z = z, x <- xs\r\n | y <- ys ]\r\n}}}\r\nThis fails with\r\n{{{\r\nFoo.hs:5:52: error:\r\n * Cannot instantiate unification variable `t0'\r\n with a type involving foralls: forall t2 t3. t3 -> t2 -> t2\r\n GHC doesn't yet support impredicative polymorphism\r\n * In a stmt of a monad comprehension:\r\n let f _ z = z, x <- xs | y <- ys\r\n In the expression:\r\n [(f y True, f x 'c') | let f _ z = z, x <- xs | y <- ys]\r\n In an equation for `foo':\r\n foo xs ys\r\n = [(f y True, f x 'c') | let f _ z = z, x <- xs | y <- ys]\r\n}}}\r\nNB: `ApplicativeDo` has a related problem: the implementation is quite different and has the effect of monomorphising the let-bound variable.","type_of_failure":"OtherFailure","blocking":[]} -->josefsjosefshttps://gitlab.haskell.org/ghc/ghc/-/issues/12143ApplicativeDo Fails to Desugar 'return True'2019-07-07T18:27:29ZMichaelBurgeApplicativeDo Fails to Desugar 'return True'ApplicativeDo correctly infers Functor if I bind an unused variable:
```
Prelude> :t \m -> do { x <- m; return True; }
\m -> do { x <- m; return True; } :: Functor f => f t -> f Bool
Prelude> :t \m -> do { m; return True; }
\m -> do { ...ApplicativeDo correctly infers Functor if I bind an unused variable:
```
Prelude> :t \m -> do { x <- m; return True; }
\m -> do { x <- m; return True; } :: Functor f => f t -> f Bool
Prelude> :t \m -> do { m; return True; }
\m -> do { m; return True; } :: Monad m => m a -> m Bool
```
It seems like if 'x' is unused, then 'x \<- m' and 'm' should be equivalent.
And maybe 'return True' should be Monad, but 'do { return True; }' should be Applicative?8.4.1Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/12360Extend support for binding implicit parameters2020-04-22T09:17:26ZMichaelBurgeExtend support for binding implicit parametersImplicit parameters can only be bound using simple let and where declarations. In this example, one would expect ?t to be bound to the result of getCurrentTime, however the program is rejected with a syntax error:
```
{-# LANGUAGE Impli...Implicit parameters can only be bound using simple let and where declarations. In this example, one would expect ?t to be bound to the result of getCurrentTime, however the program is rejected with a syntax error:
```
{-# LANGUAGE ImplicitParams #-}
import Data.Time.Clock
printTime :: (?t :: UTCTime) => IO ()
printTime = putStrLn $ show ?t
main = do
?t <- getCurrentTime
printTime
```
Instead, one must first bind to a regular variable and then bind the implicit parameter to it:
```
{-# LANGUAGE ImplicitParams #-}
import Data.Time.Clock
printTime :: (?t :: UTCTime) => IO ()
printTime = putStrLn $ show ?t
main = do
t <- getCurrentTime
let ?t = t
printTime
```
In general, it seems like any pattern binding involving implicit parameters could be rewritten as a pattern binding to ordinary variables, followed by a binding of the implicit parameters to the ordinary variables. So you could bind implicit parameters buried in variables, tuples, record fields, etc.:
Sugared:
```
{-# LANGUAGE ImplicitParams #-}
data Example = Example { a :: Int, b :: Int, c :: Int }
f :: (?a :: Int, ?b :: Int, ?c :: Int) => Int
f = ?a + ?b + ?c
main = do
let x = Example 1 2 3
let (Example { a = ?a, b = ?b, c = ?c }) = x
putStrLn $ show f
```
Desugared:
```
{-# LANGUAGE ImplicitParams #-}
data Example = Example { a :: Int, b :: Int, c :: Int }
f :: (?a :: Int, ?b :: Int, ?c :: Int) => Int
f = ?a + ?b + ?c
main = do
let x = Example 1 2 3
let (Example { a = a, b = b, c = c }) = x
let ?a = a
?b = b
?c = c
putStrLn $ show f
```https://gitlab.haskell.org/ghc/ghc/-/issues/12490With RebindableSyntax, ApplicativeDo should eliminate return/pure2019-07-07T18:26:23ZAaronFrielWith RebindableSyntax, ApplicativeDo should eliminate return/pureIn a module with -XApplicativeDo, -XRebindableSyntax, and local definitions for everything in the Functor-Applicative-Monad hierarchy, do-notation always desugars to "join (... (return ...))" (or /s/return/pure/). This forces the result ...In a module with -XApplicativeDo, -XRebindableSyntax, and local definitions for everything in the Functor-Applicative-Monad hierarchy, do-notation always desugars to "join (... (return ...))" (or /s/return/pure/). This forces the result to have at least the constraints of join, which in my case is "IxMonad m".
```hs
{-# LANGUAGE RebindableSyntax, ApplicativeDo #-}
module My where
-- straightforward definitions of fmap, pure, (<*>), join, return, (>>=),
-- (>>) and fail in terms of IxFunctor, IxPointed, IxApplicative, IxMonad
fPure m = do
a <- m
b <- m
pure (a, b)
fReturn m = do
a <- m
b <- m
return (a, b)
```
According to -ddump-ds, these desugar to:
```hs
fPure :: IxMonad m => m k1 k1 a -> m k1 k1 (a, a)
fPure m = My.join ( My.(<*>) (My.fmap (\a b -> My.pure (a, b)) m) m )
fReturn :: IxMonad m => m k1 k1 a -> m k1 k1 (a, a)
fReturn m = My.join ( My.(<*>) (My.fmap (\a b -> My.return (a, b)) m) m )
```
But I would expect:
```hs
fPure m = My.(<*>) (My.fmap (\a b -> (a, b)) m) m
fReturn m = -- same
```
It appears that when "return" is not from base, ApplicativeDo only partially desugars to the specification, and the final "return" or "pure" remains in the output.8.0.2Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/13242Panic "StgCmmEnv: variable not found" with ApplicativeDo and ExistentialQuant...2019-07-07T18:22:57ZljliPanic "StgCmmEnv: variable not found" with ApplicativeDo and ExistentialQuantification```hs
-- Panic.hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE ExistentialQuantification #-}
module Panic where
import Data.STRef
import Control.Monad.ST
data A = forall a. A a
st :: ST s ()
st = do
A _ <- pure $ A True
ref...```hs
-- Panic.hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE ExistentialQuantification #-}
module Panic where
import Data.STRef
import Control.Monad.ST
data A = forall a. A a
st :: ST s ()
st = do
A _ <- pure $ A True
ref <- newSTRef 1
readSTRef ref
pure ()
```
```
$ ghc Panic.hs
[1 of 1] Compiling Panic ( Panic.hs, Panic.o )
ghc: panic! (the 'impossible' happened)
(GHC version 8.1.20170106 for x86_64-unknown-linux):
StgCmmEnv: variable not found
$dMonad_aGQ
local binds for:
$trModule
$tcA
$tc'A
$tcA1_rSi
$tc'A1_rSJ
$trModule1_rSK
$trModule2_rSL
sat_sT5
sat_sT9
sat_sTa
Call stack:
CallStack (from HasCallStack):
prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable
callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable
pprPanic, called at compiler/codeGen/StgCmmEnv.hs:137:9 in ghc:StgCmmEnv
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
```
The above module fails to compile, giving the pasted panic message.
Without the ApplicativeDo pragma compilation succeeds.
Reproduced with GHC 8.0.2 and a recent head, courtesy of nixpkgs:
```
gp84vpgar3n3rqvkwj47yyhxvsvbsmi6-ghc-8.1.20170106
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.1 |
| 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":"Panic \"StgCmmEnv: variable not found\" with ApplicativeDo and ExistentialQuantification","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{#!hs\r\n-- Panic.hs\r\n{-# LANGUAGE ApplicativeDo #-}\r\n{-# LANGUAGE ExistentialQuantification #-}\r\nmodule Panic where\r\n\r\nimport Data.STRef\r\nimport Control.Monad.ST\r\n\r\ndata A = forall a. A a\r\n\r\nst :: ST s ()\r\nst = do\r\n A _ <- pure $ A True\r\n ref <- newSTRef 1\r\n readSTRef ref\r\n pure ()\r\n}}}\r\n\r\n{{{\r\n$ ghc Panic.hs\r\n[1 of 1] Compiling Panic ( Panic.hs, Panic.o )\r\nghc: panic! (the 'impossible' happened)\r\n (GHC version 8.1.20170106 for x86_64-unknown-linux):\r\n\tStgCmmEnv: variable not found\r\n $dMonad_aGQ\r\n local binds for:\r\n $trModule\r\n $tcA\r\n $tc'A\r\n $tcA1_rSi\r\n $tc'A1_rSJ\r\n $trModule1_rSK\r\n $trModule2_rSL\r\n sat_sT5\r\n sat_sT9\r\n sat_sTa\r\n Call stack:\r\n CallStack (from HasCallStack):\r\n prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable\r\n callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable\r\n pprPanic, called at compiler/codeGen/StgCmmEnv.hs:137:9 in ghc:StgCmmEnv\r\n\r\nPlease report this as a GHC bug: http://www.haskell.org/ghc/reportabug\r\n}}}\r\n\r\nThe above module fails to compile, giving the pasted panic message.\r\nWithout the ApplicativeDo pragma compilation succeeds.\r\nReproduced with GHC 8.0.2 and a recent head, courtesy of nixpkgs:\r\n{{{\r\ngp84vpgar3n3rqvkwj47yyhxvsvbsmi6-ghc-8.1.20170106\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->8.2.1Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/13309Use liftA2 in ApplicativeDo2020-01-23T19:31:53ZDavid FeuerUse liftA2 in ApplicativeDoNow that `liftA2` is in `Applicative`, we want to be sure to use it when desugaring `ApplicativeDo`.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Versio...Now that `liftA2` is in `Applicative`, we want to be sure to use it when desugaring `ApplicativeDo`.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.1 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Use liftA2 in ApplicativeDo","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.4.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"Now that `liftA2` is in `Applicative`, we want to be sure to use it when desugaring `ApplicativeDo`.","type_of_failure":"OtherFailure","blocking":[]} -->AaronFrielAaronFrielhttps://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/13648ApplicativeDo selects "GHC.Base.Monad.return" when actions are used without p...2019-07-07T18:20:47ZAaronFrielApplicativeDo selects "GHC.Base.Monad.return" when actions are used without patterns.GHC 8.0.2 and 8.2.1-rc1 (rc2 not checked) have a bug where -XApplicativeDo causes "GHC.Base.Monad.return" to be used instead of the locally available "return", and a spurious "return ()" shows up. This desugaring is not adhering to the -...GHC 8.0.2 and 8.2.1-rc1 (rc2 not checked) have a bug where -XApplicativeDo causes "GHC.Base.Monad.return" to be used instead of the locally available "return", and a spurious "return ()" shows up. This desugaring is not adhering to the -XRebindableSyntax spec (see: #12490).
Example:
```hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RebindableSyntax #-}
-- Bug vanishes if this next line is removed:
{-# LANGUAGE ApplicativeDo #-}
module Main where
import Prelude (String, print)
class MyFunctor f where
fmap :: (a -> b) -> f a -> f b
class MyApplicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class MyMonad m where
return :: a -> m a
(>>) :: m a -> m b -> m b
(>>=) :: m a -> (a -> m b) -> m b
fail :: String -> m a
join :: m (m a) -> m a
testCase1 m1 m2 = do
m1
m2
return ()
testCase2 m1 m2 = do
_ <- m1
_ <- m2
return ()
main = print "42"
```
```
:t testCase1
testCase1
:: (MyFunctor f, MyApplicative f, MyMonad f, Monad f) =>
f a2 -> f a1 -> f ()
:t testCase2
:: testCase2 :: (MyFunctor f, MyApplicative f) => f t -> f a -> f ()
```
The desugaring for testCase1 shows the issue:
```hs
testCase1' m1 m2 =
(<*>)
(fmap
(\ r1 r2 ->
case r1 of { () -> case r2 of { () -> () } })
(m1 >> (GHC.Base.Monad.return ())))
(m2 >> (GHC.Base.Monad.return ()))
-- or:
testCase1'' m1 m2 = (fmap (\() () -> () ) (m1 >> (GHC.Base.Monad.return ()))) <*> (m2 >> (GHC.Base.Monad.return ()))
```
I would be able to work on this if someone pointed me in the right direction. It looks like it would be in `compiler/rename/RnEnv` and `compiler/rename/RnExpr`, as with #12490?
As a proposed fix, I would want to implement a limited-scope fix before the 8.2.1 release which would not address the thornier issue of #10892. The patch would:
1. Replace `GHC.Base.Monad.return` with local `pure`, removing the `Monad` constraint.
1. Replace `>>` with `*>`, removing the `MyMonad` constraint.
This isn't a _complete_ fix, as this would still leave the unnecessary pattern matches in the use of `fmap`. The resulting desugaring would be:
```hs
testCase1''' m1 m2 = (fmap (\() () -> () ) (m1 *> (pure ()))) <*> (m2 *> (pure ()))
```https://gitlab.haskell.org/ghc/ghc/-/issues/13875ApplicativeDo desugaring is lazier than standard desugaring2019-07-07T18:19:43ZDavid FeuerApplicativeDo desugaring is lazier than standard desugaringSuppose 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. Th...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 ()
```
<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 desugaring is lazier than standard desugaring","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.4.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.3","keywords":["ApplicativeDo"],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"Bug","description":"Suppose I write\r\n\r\n{{{#!hs\r\nimport Data.Maybe (isJust)\r\n\r\nbangy m = do\r\n (_,_) <- m\r\n return ()\r\n\r\nmain = print $ isJust (bangy (Just undefined))\r\n}}}\r\n\r\nIf 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:\r\n\r\n{{{#!hs\r\nbangy m = do\r\n ~(_,_) <- m\r\n return ()\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->8.2.1Simon MarlowSimon Marlowhttps://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":[]} -->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/14105ApplicativeDo causes GHC panic on irrefutable list pattern match2019-07-07T18:18:27ZBoteboTseboApplicativeDo causes GHC panic on irrefutable list pattern matchSo this just happened:
```hs
{-# language ApplicativeDo #-}
module Main where
main :: IO ()
main = do
[_] <- pure []
pure ()
```
Compiling (under Stack) with `stack exec -- ghc --make src/Main.hs` yields
```
[1 of 1] Compiling Ma...So this just happened:
```hs
{-# language ApplicativeDo #-}
module Main where
main :: IO ()
main = do
[_] <- pure []
pure ()
```
Compiling (under Stack) with `stack exec -- ghc --make src/Main.hs` yields
```
[1 of 1] Compiling Main ( src/Main.hs, src/Main.o )
ghc: panic! (the 'impossible' happened)
(GHC version 8.2.1 for x86_64-unknown-linux):
isStrictPattern
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
```
This does not happen on GHC-8.0.2. It does not happen when `ApplicativeDo` is not activated. It also does not happen when the pattern match line is changed to
```hs
[] <- pure []
```
For completeness, the compiler used by `stack` is that which comes with `nightly-2017-08-10`. I am on Linux x64 (Ubuntu).
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.1 |
| 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 causes GHC panic on irrefutable list pattern match","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["ApplicativeDo"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"So this just happened:\r\n\r\n{{{#!hs\r\n{-# language ApplicativeDo #-}\r\nmodule Main where\r\n\r\nmain :: IO ()\r\nmain = do\r\n [_] <- pure []\r\n pure ()\r\n}}}\r\n\r\nCompiling (under Stack) with `stack exec -- ghc --make src/Main.hs` yields\r\n{{{\r\n[1 of 1] Compiling Main ( src/Main.hs, src/Main.o )\r\nghc: panic! (the 'impossible' happened)\r\n (GHC version 8.2.1 for x86_64-unknown-linux):\r\n\tisStrictPattern\r\n\r\nPlease report this as a GHC bug: http://www.haskell.org/ghc/reportabug\r\n}}}\r\n\r\nThis does not happen on GHC-8.0.2. It does not happen when `ApplicativeDo` is not activated. It also does not happen when the pattern match line is changed to\r\n{{{#!hs\r\n [] <- pure []\r\n}}}\r\n\r\n\r\nFor completeness, the compiler used by `stack` is that which comes with `nightly-2017-08-10`. I am on Linux x64 (Ubuntu).","type_of_failure":"OtherFailure","blocking":[]} -->8.4.1https://gitlab.haskell.org/ghc/ghc/-/issues/14163Stack Overflow with ApplicativeDo2019-07-07T18:18:12ZlipplingStack Overflow with ApplicativeDoI tried to compile one of our server applications with 8.2.1 (which compiles fine with 8.0.2).
The compilation runs smoothly, but when it reaches a specific file, the RAM usage goes up to \> 20GB pretty fast on my 16GB machine and the G...I tried to compile one of our server applications with 8.2.1 (which compiles fine with 8.0.2).
The compilation runs smoothly, but when it reaches a specific file, the RAM usage goes up to \> 20GB pretty fast on my 16GB machine and the GHC process gets terminated with a stack overflow error.
I tried to find a minimal example that causes this behavior:
```hs
#!/usr/bin/env stack
-- stack --resolver nightly-2017-08-25 script
{-# LANGUAGE ApplicativeDo #-}
x = do
(a, _) <- undefined
(b, _) <- undefined
(c, _) <- undefined
undefined
main = undefined
```
It only happens with at least 3 of these pattern matches.8.2.2Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/14249ApplicativeDo: Pattern matching on a bind forces a Monad constraint2023-11-20T09:52:01ZmutantmellApplicativeDo: Pattern matching on a bind forces a Monad constraintPattern matching on a bind in 8.2.1 confuses ApplicativeDo, and causes the type to have a Monad constraint where a Functor constraint would suffice.
In GHC 8.0:
```hs
> :set -XApplicativeDo
> :t \x -> do { (a, _) <- x; pure (a+1) }
\x ...Pattern matching on a bind in 8.2.1 confuses ApplicativeDo, and causes the type to have a Monad constraint where a Functor constraint would suffice.
In GHC 8.0:
```hs
> :set -XApplicativeDo
> :t \x -> do { (a, _) <- x; pure (a+1) }
\x -> do { (a, _) <- x; pure (a+1) }
:: (Num b, Functor f) => f (b, t) -> f b
```
In GHC 8.2:
```hs
> :set -XApplicativeDo
> :t \x -> do { (a, _) <- x; pure (a+1) }
\x -> do { (a, _) <- x; pure (a+1) }
:: (Num b1, Monad m) => m (b1, b2) -> m b1
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.1 |
| 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: Pattern matching on a bind forces a Monad constraint","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["ApplicativeDo"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Pattern matching on a bind in 8.2.1 confuses ApplicativeDo, and causes the type to have a Monad constraint where a Functor constraint would suffice.\r\n\r\nIn GHC 8.0:\r\n\r\n{{{#!hs\r\n> :set -XApplicativeDo\r\n> :t \\x -> do { (a, _) <- x; pure (a+1) }\r\n\\x -> do { (a, _) <- x; pure (a+1) }\r\n :: (Num b, Functor f) => f (b, t) -> f b\r\n}}}\r\n\r\nIn GHC 8.2:\r\n\r\n{{{#!hs\r\n> :set -XApplicativeDo\r\n> :t \\x -> do { (a, _) <- x; pure (a+1) }\r\n\\x -> do { (a, _) <- x; pure (a+1) }\r\n :: (Num b1, Monad m) => m (b1, b2) -> m b1\r\n}}}","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/14471Certain do blocks cause TH to barf when ApplicativeDo is enabled2019-07-07T18:16:54ZAlexis KingCertain do blocks cause TH to barf when ApplicativeDo is enabledThe following program fails with an error:
```hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE TemplateHaskell #-}
main = $([|do
return ()
return ()
return ()|])
```
```
Exotic.hs:4:12: error:
Exotic statement not (yet) handle...The following program fails with an error:
```hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE TemplateHaskell #-}
main = $([|do
return ()
return ()
return ()|])
```
```
Exotic.hs:4:12: error:
Exotic statement not (yet) handled by Template Haskell
[return ();
return (),
return ()]
```
It only happens when `ApplicativeDo` is enabled.
Furthermore, while this example is extremely minimal, this issue isn’t restricted to `ApplicativeDo`’s special handling of `return`. The following example produces the same error:
```hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE TemplateHaskell #-}
main = $([|do
getLine
getLine
getLine|])
```
```
Exotic.hs:4:12: error:
Exotic statement not (yet) handled by Template Haskell
[getLine;
getLine,
getLine]
```
This *doesn’t* happen with fewer than three statements in the `do` block, but it *does* happen with more.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Certain do blocks cause TH to barf when ApplicativeDo is enabled","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The following program fails with an error:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE ApplicativeDo #-}\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\nmain = $([|do\r\n return ()\r\n return ()\r\n return ()|])\r\n}}}\r\n{{{\r\nExotic.hs:4:12: error:\r\n Exotic statement not (yet) handled by Template Haskell\r\n [return ();\r\n return (),\r\n return ()]\r\n}}}\r\n\r\nIt only happens when `ApplicativeDo` is enabled.\r\n\r\nFurthermore, while this example is extremely minimal, this issue isn’t restricted to `ApplicativeDo`’s special handling of `return`. The following example produces the same error:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE ApplicativeDo #-}\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\nmain = $([|do\r\n getLine\r\n getLine\r\n getLine|])\r\n}}}\r\n{{{\r\nExotic.hs:4:12: error:\r\n Exotic statement not (yet) handled by Template Haskell\r\n [getLine;\r\n getLine,\r\n getLine]\r\n}}}\r\n\r\nThis ''doesn’t'' happen with fewer than three statements in the `do` block, but it ''does'' happen with more.","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1Michael SloanMichael Sloanhttps://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/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/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/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.1https://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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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.