Skip to content

Static Pointers with type classes generate misleading errors

Summary

Using static with members of type classes generates unexpected and misleading type errors. The type errors produced by GHC complain about unsatisfiable type class constraints when the problem is (implicitly) that there is an unclosed argument.

Steps to reproduce

{-# LANGUAGE StaticPointers #-}
{-# LANGUAGE GADTs #-}

import Type.Reflection (TypeRep, Typeable, typeRep)
import GHC.StaticPtr

data Dynamic where
  Typed :: a -> StaticPtr (TypeRep a) -> Dynamic

toDyn :: (Typeable a) => a -> Dynamic
toDyn x = Typed x (static typeRep)

main :: IO ()
main = undefined

Compiling this produces the following error:

    • No instance for (Typeable a) arising from a use of ‘typeRep’
    • In the body of a static form: typeRep
      In the second argument of ‘Typed’, namely ‘(static typeRep)’
      In the expression: Typed x (static typeRep)
   |
11 | toDyn x = Typed x (static typeRep)
   |                           ^^^^^^^

The type error is unexpected, given that the assumption that static can be thought of as static :: a -> StaticPtr a. We can then introduce a function

static2 :: a -> StaticPtr a
static2 = undefined

and replacing static with static2 allows the code to typecheck.

Expected behavior

When using static with the member of a type class, this should be treated the same, or similar to using static with an unclosed argument.

Environment

  • GHC version used: 8.6.5

Optional:

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