Skip to content

Surprising interaction between representation defaulting and type families

Summary

Defaulting types to Type leads to surprising matching in type families.

{-# LANGUAGE TypeFamilies, PolyKinds, StandaloneKindSignatures, ScopedTypeVariables #-}
module Bork where
import GHC.Exts

type IsArr :: forall rep. TYPE rep -> Bool
type family IsArr f where
  IsArr (a -> b) = 'True
  IsArr _ = 'False

What would you expect :kind! (IsArr Char#) to be? Well, I would certainly expect it to be 'False. However, it's actually a stuck type! The problem is that GHC has defaulted rep to 'LiftedRep, making something like

type family IsArr f where
  IsArr @'LiftedRep (a -> b) = 'True
  IsArr @'LiftedRep _ = 'False

It's possible to work around the problem like so

type IsArr :: forall rep. TYPE rep -> Bool
type family IsArr f where
  IsArr (a -> b) = 'True
  IsArr @rep _ = 'False

but this strikes me as horrible counterintuitive.

Environment

  • GHC version used: 9.0

Optional:

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