Checking that two values have the same head constructor

Viewed 351

I'd like to be able to write a function which checks that two values have been built using the same head constructor. This function:

  • shouldn't be linear in the size of the datatype declaration

  • should keep working if the datatype is extended

e.g. this is not satisfactory (it is linear and the catchall will invalidate the function if I add any extra constructor):

data E = A Int | B String | C

sameCons :: E -> E -> Bool
sameCons t u = case (t, u) of
  (A{}, A{}) -> True
  (B{}, B{}) -> True
  (C{}, C{}) -> True
  _          -> False

In OCaml it is possible to use unsafe functions from the Obj module to do exactly that. Can we do something similar in Haskell (a ghc-specific solution works too)?

3 Answers

We ended up needing a datatype of constructor names anyway so here is our current solution which does not rely on Data or GHC.Generics:

data E = A Int | B String | C
data EName = A_ | B_ | C_ deriving (Eq)

eName :: E -> EName
eName e = case e of
  A{} -> A_
  B{} -> B_
  C{} -> C_

sameCons :: E -> E -> Bool
sameCons = (==) `on` eName
Related