Skip to content

language pragma order matters

Summary

Speculating a little bit: when one extension implies another, that overrides previous explicit requests about whether the implied extension should be on or not. I think explicit user request should take precedence over the implicit requests by implication. (And, generally, I think the order that language pragmas are declared in should not matter.)

Steps to reproduce

The following code compiles fine:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoMonoLocalBinds #-}

data Data = Data { foo :: Int, bar :: Double }

baz :: Data -> Data -> Bool
baz d1 d2 = check foo && check bar where
  check f = f d1 == f d2

However, switching the order of the pragmas causes it to stop compiling:

{-# LANGUAGE NoMonoLocalBinds #-}
{-# LANGUAGE TypeFamilies #-}

data Data = Data { foo :: Int, bar :: Double }

baz :: Data -> Data -> Bool
baz d1 d2 = check foo && check bar where
  check f = f d1 == f d2

For completeness, I'll include the error, though I think the cause is probably pretty clear:

test.hs:7:32: error:
    • Couldn't match type ‘Double’ with ‘Int’
      Expected type: Data -> Int
        Actual type: Data -> Double
    • In the first argument of ‘check’, namely ‘bar’
      In the second argument of ‘(&&)’, namely ‘check bar’
      In the expression: check foo && check bar
  |
7 | baz d1 d2 = check foo && check bar where
  |                                ^^^

Expected behavior

I expect both code snippets to compile without error.

Environment

  • GHC version used: 8.8.1
  • Operating System: Fedora 30, Linux 5.3.7
  • System Architecture: x86-64
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information