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)