[GHC] #15034: Desugaring `mdo` moves a `let` where it shouldn't be

GHC ghc-devs at haskell.org
Tue Apr 17 08:41:35 UTC 2018


#15034: Desugaring `mdo` moves a `let` where it shouldn't be
-------------------------------------+-------------------------------------
        Reporter:  parsonsmatt       |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.6.1
       Component:  Compiler          |              Version:  8.2.2
      Resolution:                    |             Keywords:  RecursiveDo
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Changes (by simonpj):

 * keywords:   => RecursiveDo


Comment:

 That is indeed odd.  Are you sure your example is right in comment:2?  You
 don't even use `theUsual` before its definition in the "However, when I
 move..." version.

 The `weiddlyLocal` example in the Description is more comprehensible.
 After dependency analysis we get
 {{{
 thisWorks :: IO ()
 thisWorks = do
     let weirdlyLocal1 = theThing
     runSTIO weirdlyLocal1
     runSTIO weirdlyLocal1

 thisBreaks :: IO ()
 thisBreaks = do
     rec { runSTIO weirdlyLocal2
         ; let weirdlyLocal2 = theThing
     runSTIO weirdlyLocal2 }
 }}}
 I've made the recursive block explicit.  No `rec` is needed in the first
 example, and we get
 {{{
 weirdlyLocal1 :: forall s. ST s ()
 }}}
 But in the second example we have recursion, and like all reduction (at
 least without
 type signatures) in Haskell, it is monomorphic.  So in the recursive block
 we get
 {{{
 weirdlyLocal2 :: ST s0 ()
 }}}
 where `s0` is some monomorphic type.  So `weirdlyLocal2` is not
 polymoprhic enough to
 give to `runSTIO`, hence breakage.

 Another way to think of it is to imagine typing this:
 {{{
 thisBreaks = do
     weirdlyLocal2 <- mfix (\wl2 -> do { runSTIO wl2
                                       ; let weirdlyLocal2 = theThing
                                       ; return weirdlyLocal2 })
     runSTIO weirdlyLocal2 }
 }}}
 Here you can see that the lambda-bound `wl2` would get a monormorphic
 type.

 I don't think anyone has studied how to do ''polymorphic'' recursion
 in `mdo`.  But it'd be interesting to try.

 Trac #7842 is another report of the same problem.

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


More information about the ghc-tickets mailing list