
Hello, I often find it useful to determine whether two objects are using the same constructor, without worrying about the constructors' arguments. An example, using some arbitrary data type "Thingo":
class ShallowEq a where shallowEq :: a -> a -> Bool
data Thingo a b = TOne a | TTwo a b Int Char Float | TThree Int Char b b
(TOne 23) `shallowEq` TOne{} True
(TThree 5 'c' True False) `shallowEq` TTwo{} False
-- Having some sort of generic shallowEq operator reduces the need for a host of predicates such as: (this one from Data.Maybe)
isJust x = case x of Just {} -> True _ -> False
.. which is an approach that is obviously going to be tedious when the size of the data type becomes large. -- There is way to hack together a partial implementation of the ShallowEq class within GHC, but it leaves much to be desired:
instance Show a => ShallowEq a where (=@=) a b = (head $ words $ show a) == (head $ words $ show b)
Notice that in the example the term "TTwo{}" is a partially constructed record. The implementation relies on laziniess to avoid trying to show the missing fields (which would fail). -- Questions: 1) Does anyone know a better/existing way to implement ShallowEq that doesn't involve enumerating all the constructors in the data type? 2) If not, can anyone think of reasons why it wouldn't be a good idea for GHC to derive ShallowEq (by expanding said enumeration)?