在我的项目中,我创建了一种数据类型,它可以保存几种类型的值之一:
data PhpValue = VoidValue | IntValue Integer | BoolValue Bool
我现在想做的是有一种简单的方法来检查两个值是否PhpValue
类型具有相同的构造函数(如果我对这里的术语感到困惑,请纠正我,但基本上我想检查两者是否是,例如IntValue
,而不关心特定值)。
这是我为此编写的一个函数:
sameConstructor :: PhpValue -> PhpValue -> Bool
sameConstructor VoidValue VoidValue = True
sameConstructor (IntValue _) (IntValue _) = True
sameConstructor (BoolValue _) (BoolValue _) = True
sameConstructor _ _ = False
这可以正常工作,但我真的不喜欢它:如果我添加更多构造函数(例如FloatValue Float
)我将不得不重写该函数,并且随着我的数据定义变大,它也会变大。
问题:有没有一种方法可以编写这样的函数,以便当我添加更多构造函数时它的实现不会改变?
郑重声明:我不想改变data
定义,我的其余代码中有足够的 Monad;)
看一眼Data.Data
和它的toConstr
功能。这将返回构造函数的表示形式,可以比较其是否相等。
使用扩展名(您可以将{-# LANGUAGE DeriveDataTypeable #-}
在模块的顶部),您可以有一个Data
自动为您派生实例:
data PhpValue = VoidValue | IntValue Integer | BoolValue Bool
deriving (Typeable, Data)
然后您应该能够使用toConstr
通过构造函数进行比较的函数。
现在以下情况将成立:
toConstr (BoolValue True) == toConstr (BoolValue False)
Using on
from Data.Function
你现在可以重写sameConstructor
to:
sameConstructor = (==) `on` toConstr
这与
sameConstructor l r = toConstr l == toConstr r
我认为使用的版本on
更容易一目了然地阅读。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)