通过构造函数比较值

Comparing values by their constructors

我有一个这样定义的数据类型:

data Token
  = Literal Integer
  | Operator String
  | Separator Char
  | Identifier String

如果我有一个 Token 类型的值,有没有一种优雅的方法来检查它的类型构造函数是否是例如Operator?甚至更多:有没有办法检查 Token 类型的两个值是否是同一构造函数的实例?

我显然可以创建函数:

isOperator :: Token -> Bool
isOperator (Operator _) = True
isOperator _ = False

haveSameConstructor :: Token -> Token -> Bool
haveSameConstructor (Literal _) (Literal _) = True
haveSameConstructor (Operator _) (Operator _) = True
haveSameConstructor (Separator _) (Separator _) = True
haveSameConstructor (Identifier _) (Identifier _) = True
haveSameConstructor _ = False

但是,这确实很冗长,尤其是当该类型具有更多构造函数时。或者我可以使用 case ... of 但是当我需要比较构造函数时总是使用它对我来说似乎是重复的。有什么聪明的解决办法吗?例如。类似于函数 isKindOf Operator token.

感谢 user1984 posting a link to this question 我找到了解决方案:

{-# LANGUAGE DeriveDataTypeable #-}
import Data.Data

data Token
  = Literal Integer
  | Operator String
  | Separator Char
  | Identifier String deriving (Show, Eq, Typeable)

sameConstructor :: Token -> Token -> Bool
sameConstructor a b = toConstr a == toConstr b

它不允许我检查某个值是否是特定构造函数的实例,但至少我可以通过比较两个值来替换它 sameConstructor token (Operator "")