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/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/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/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/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/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/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/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/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/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/1313595873058750464