Checking that two values have the same head constructor

If you're willing to derive Data then you're good to go.

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Data

data E = A Int | B String | C deriving (Typeable, Data)

sameCons :: E -> E -> Bool
sameCons x y = toConstr x == toConstr y

ghci> sameCons (A 1) (A 3)
True
ghci> sameCons (A 1) (C)
False

You can also do this with GHC.Generics, but it's more boilerplate than The Orgazoid's answer.

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}

import Data.Function (on)
import GHC.Generics

class GSameCons f where
  gSameCons :: f p -> f p -> Bool

instance GSameCons f => GSameCons (D1 c f) where
  gSameCons (M1 a) (M1 b) = gSameCons a b

instance (GSameCons f, GSameCons g) => GSameCons (f :+: g) where
  gSameCons (L1 a) (L1 b) = gSameCons a b
  gSameCons (R1 a) (R1 b) = gSameCons a b
  gSameCons _ _ = False

instance GSameCons (C1 c f) where
  gSameCons _ _ = True

data E = A Int | B String | C deriving Generic

sameCons :: (GSameCons (Rep a), Generic a) => a -> a -> Bool
sameCons = gSameCons `on` from

main = do
  print (sameCons (A 1) (A 2))
  print (sameCons (B "") C)

Tags:

Haskell