[GHC] #13648: ApplicativeDo selects "GHC.Base.Monad.return" when actions are used without patterns.

GHC ghc-devs at haskell.org
Fri May 5 09:58:27 UTC 2017


#13648: ApplicativeDo selects "GHC.Base.Monad.return" when actions are used without
patterns.
-------------------------------------+-------------------------------------
        Reporter:  AaronFriel        |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.2.1-rc1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  GHC rejects       |  Unknown/Multiple
  valid program                      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Description changed by AaronFriel:

@@ -61,1 +61,2 @@
-            (\() () -> ())
+            (\ r1 r2 ->
+               case r1 of { () -> case r2 of { () -> () } })
@@ -65,2 +66,2 @@
- testCase1' m1 m2 = (fmap (\() () -> () ) (m1 >> (return ()))) <*> (m2 >>
- (return ()))
+ testCase1'' m1 m2 = (fmap (\() () -> () ) (m1 >> (GHC.Base.Monad.return
+ ()))) <*> (m2 >> (GHC.Base.Monad.return ()))
@@ -81,3 +82,8 @@
- This isn't a _complete_ fix, as this would still induce an unnecessary use
- of the local `fmap`, but it would reduce the desugaring bug in `testCase1`
- to only that local `fmap`.
+ 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 ()))
+ }}}

New description:

 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.
 2. 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 ()))
 }}}

--

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13648#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list