Skip to content

mdo should use HsExpansion Route

Summary

mdo (recursive do statements) should follow the same flow of vanilla do statements and not depend on tcSyntaxOp

Steps to reproduce

{-# LANGUAGE ImpredicativeTypes, RecursiveDo #-}

type Id = forall a. a -> a

t :: IO (forall a. a -> a)
t = return id

p :: (forall a. a -> a) -> (Bool, Int)
p f = (f True, f 3)

-- This does *not* type check:
foo2 = mdo { x <- t ; return (p x) }

Fails with:

testsuite/tests/typecheck/should_run/T18324.hs:13:19: error: [GHC-91028]
    • Couldn't match type ‘a0’ with ‘Id’
      Expected: IO a0
        Actual: IO Id
      Cannot instantiate unification variable ‘a0’
      with a type involving polytypes: Id
    • In a stmt of an 'mdo' block: x <- t
      In the expression:
        mdo x <- t
            return (p x)
      In an equation for ‘foo2’:
          foo2
            = mdo x <- t
                  return (p x)
   |
13 | foo2 = mdo { x <- t ; return (p x) }
   |                   ^

testsuite/tests/typecheck/should_run/T18324.hs:13:33: 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:
          Id
        at testsuite/tests/typecheck/should_run/T18324.hs:13:33
    • In the first argument of ‘p’, namely ‘x’
      In the first argument of ‘return’, namely ‘(p x)’
      In a stmt of an 'mdo' block: return (p x)
    • Relevant bindings include
        x :: a0
          (bound at testsuite/tests/typecheck/should_run/T18324.hs:13:14)
   |
13 | foo2 = mdo { x <- t ; return (p x) }

Expected behavior

Should typecheck and run without errors

Environment

  • GHC version used: 9.6.4
Edited by sheaf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information