Skip to content

Global ImplicitParams technique doesn't work with optimizations enabled

Summary

When using the Global Implicit Parameters technique described in this blog post with optimizations, I observe that it doesn't work. Specifically, the global parameter is applied always, even when I override it locally. The following test:

    describe "Colour disabling works" $ do
        it "Disable yellow" $
            let ?colourMode = DisableColour
            in yellow @Text `shouldBe` ""

doesn't pass with the following error:

  test/Test/Colourista.hs:44:16: 
  1) Colourista tests, Colour disabling works, Disable yellow
       expected: ""
        but got: "\ESC[93m"

Specifically, I'm trying to use ImplicitParams to implement colour disabling and enabling in the colourista library. See the following PRs for implementation:

In short, the implementation looks like this:

data ColourMode
    = DisableColour
    | EnableColour
    deriving stock (Show, Eq, Enum, Bounded)

instance IP "colourMode" ColourMode where
    ip = EnableColour

type HasColourMode = (?colourMode :: ColourMode)

withColourMode :: (HasColourMode, IsString str) => str -> str
withColourMode str = case ?colourMode of
    EnableColour  -> str
    DisableColour -> ""
{-# INLINE withColourMode #-}

-- | Code to apply 'Yellow' colouring for the terminal output.
yellow :: (HasColourMode, IsString str) => str
yellow = withColourMode $ fromString $ setSGRCode [SetColor Foreground Vivid Yellow]
{-# SPECIALIZE yellow :: HasColourMode => String     #-}
{-# SPECIALIZE yellow :: HasColourMode => Text       #-}
{-# SPECIALIZE yellow :: HasColourMode => ByteString #-}

However, this implementation only works when I build the project with -O0. Morever, I see the following warnings, which emitted only when I build the project without -O0:

src/Colourista/Pure.hs:92:1: warning: [-Wredundant-constraints]
     Redundant constraint: HasColourMode
     In the type signature for:
           red :: HasColourMode => String
      In the SPECIALISE pragma
        {-# SPECIALIZE red :: HasColourMode => String #-}
   |
92 | {-# SPECIALIZE red :: HasColourMode => String     #-}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/Colourista/Pure.hs:92:1: warning:
    Forall'd constraint HasColourMode is not bound in RULE lhs
      Orig bndrs: [$dIP_a7Qk]
      Orig lhs: let {
                  $dIsString_a7Qn :: IsString String
                  [LclId]
                  $dIsString_a7Qn = $dIsString_a7vq } in
                let {
                  $dIP_a7Qm :: HasColourMode
                  [LclId]
                  $dIP_a7Qm = Colourista.Mode.$fIP"colourMode"ColourMode } in
                red @ String $dIP_a7Qm $dIsString_a7Qn
      optimised lhs: red @ String $dIP_a7Qm $dIsString_a7Qn
   |
92 | {-# SPECIALIZE red :: HasColourMode => String     #-}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Steps to reproduce

  1. Clone the colourista repository.
  2. Checkout to branch chshersh/41-Add-some-tests
  3. Run tests: cabal test --enable-tests --test-show-details=direct

Expected behavior

Tests are passing.

Environment

  • GHC-8.8.3. But the error is reproducible with any GHC version.

Optional:

  • Operating System: Ubuntu
  • System Architecture: x86_64
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information