Haskell - 简单的构造函数比较(?)函数 [英] Haskell - simple constructor comparison (?) function
问题描述
在我的项目中,我创建了一个数据类型,它可以包含以下几种类型的值之一:
In my project I have created a data type, that can hold one of a few types of values:
data PhpValue = VoidValue | IntValue Integer | BoolValue Bool
我现在想做的是有一种简单的方法来检查 PhpValue
类型的两个值是否具有相同的构造函数(如果我对这里的术语感到困惑,请纠正我,但基本上我想检查两者是否都是,例如,IntValue
,而不关心特定值).
What I wanted to do now, is to have a simple way of checking if two values of the PhpValue
type are of the same constructor (correct me if I'm confused with the terminology here, but basically what I want to check if both are, for example, are IntValue
, without caring about the particular value).
这是我为此编写的函数:
Here is a function I wrote for that:
sameConstructor :: PhpValue -> PhpValue -> Bool
sameConstructor VoidValue VoidValue = True
sameConstructor (IntValue _) (IntValue _) = True
sameConstructor (BoolValue _) (BoolValue _) = True
sameConstructor _ _ = False
这可以正常工作,但我并不真正喜欢它:如果我添加更多构造函数(例如 FloatValue Float
),我将不得不重写该函数,它会变得更大随着我的数据定义变得越来越大.
This works as it should, but I don't really like it: if I add more constructors (like FloatValue Float
) I am going to have to rewrite the function, and it will get bigger as my data definition gets bigger.
问题: 有没有办法编写这样的函数,这样当我添加更多构造函数时它的实现不会改变?
The Question: Is there a way of writing such a function, so that its implementation doesn't change when I add more constructors?
为了记录:我不想更改 data
定义,我的其余代码中有足够的 Monads ;)
For the record: I don't want to change the data
definition, I have enough Monads in the rest of my code as it is ;)
推荐答案
看看 Data.Data
和它的 toConstr
函数.这将返回构造函数的表示形式,可以比较是否相等.
Take a look at Data.Data
and its toConstr
function. This returns a representation of the constructor which can be compared for equality.
通过扩展(您可以将 {-# LANGUAGE DeriveDataTypeable #-}
放在模块顶部),您可以自动为您派生一个 Data
实例:
With an extension (you can put {-# LANGUAGE DeriveDataTypeable #-}
at the top of your module), you can have a Data
instance derived for you automatically:
data PhpValue = VoidValue | IntValue Integer | BoolValue Bool
deriving (Typeable, Data)
然后您应该可以使用 toConstr
函数通过构造函数进行比较.
You should then be able to use the toConstr
function to compare by constructor.
现在以下将成立:
toConstr (BoolValue True) == toConstr (BoolValue False)
使用 Data.Function
中的 on
您现在可以将 sameConstructor
重写为:
Using on
from Data.Function
you can now rewrite sameConstructor
to:
sameConstructor = (==) `on` toConstr
这个是一样的
sameConstructor l r = toConstr l == toConstr r
我认为使用 on
的版本更容易一目了然.
I think the version using on
is easier to read at a glance.
这篇关于Haskell - 简单的构造函数比较(?)函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!