Haskell - 简单的构造函数比较(?)函数 [英] Haskell - simple constructor comparison (?) function

查看:28
本文介绍了Haskell - 简单的构造函数比较(?)函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我创建了一个数据类型,它可以包含以下几种类型的值之一:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆