-
Notifications
You must be signed in to change notification settings - Fork 16
Description
There are four singleton types currently defined in base
:
TypeRep
, defined inType.Reflection
SSymbol
, defined inGHC.TypeLits
SChar
, defined inGHC.TypeLits
SNat
, defined inGHC.TypeNats
SSymbol
, SChar
, and SNat
were introduced as part of proposal #85, and their APIs were designed to mimic that of TypeRep
. Unfortunately, #85 forgot to carry over one aspect of the TypeRep
API: the Eq
and Ord
instances:
instance Eq (TypeRep a) where
_ == _ = True
instance Ord (TypeRep a) where
compare _ _ = EQ
I propose that we define similar Eq
and Ord
instances for SSymbol
, SChar
, and SNat
.
How?
How can we know that the Eq
and Ord
instances for TypeRep
always return True
/EQ
? This is because TypeRep
is a singleton type. That is, given a fixed type a
, there is only ever a single unique value¹ that can inhabit type TypeRep a
. Therefore, the equality checks that (==)
and compare
perform will always succeed by virtue of the typing discipline involved.
The same reasoning applies to all other singleton types, including SSymbol
, SChar
, and SNat
.
Why?
Why bother defining these instances in the first place? On their own, they aren't terribly useful, as (==)
/compare
will always compute the same answer. They are more useful for the purpose of satisfying superclasses of other instances. For instance, the EqP
class in the some
library requires a quantified Eq
superclass, so it would not be possible to define an EqP
instance for TypeRep
(or any other singleton type) without first giving it an Eq
instance.
Prior art
TypeRep
is the most notable singleton type to define Eq
/Ord
instances in this fashion. Besides TypeRep
, I have also found other occurrences of these sort of Eq
/Ord
instances in the wild:
SNat
, defined insingleton-nats
SBool
, defined insingleton-bool
BoolRepr
,NatRepr
, andSymbolRepr
, defined inparameterized-utils
¹ Besides ⊥
, but it is fine to reason modulo ⊥
.