haskell - 定义枚举子类型不是序数的序数类型
问题描述
我遇到了定义其值可能是也可能不是序数的序数类型的问题。
基本上我有两种类型,一个OrderedType
和一个UnorderedType
data OrderedType = One | Two | Three deriving (Eq, Ord, Show)
data UnorderedType = Red | Blue | Green deriving (Eq, Show)
我有一个类型,其值构造函数将任何一个作为参数:
data WrapperType = WrappedOne OrderedType
| WrappedTwo UnorderedType deriving (Eq, Ord, Show)
基本上,我想要做的是WrapperType
无需为and实现compare
函数即可订购 s 。WrappedOne
WrappedTwo
当我尝试编译上述内容时,出现以下错误:
• No instance for (Ord UnorderedType)
arising from the first field of ‘WrappedTwo’ (type ‘UnorderedType’)
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
• When deriving the instance for (Ord WrappedType)
这是有道理的,因为股票派生Ord
实例WrappedType
将尝试比较 的所有值WrappedTwo
。
简而言之,我想要做的是:
WrappedOne _ < WrappedTwo _ -- True
Ord
但是没有为每种类型编写一个实例。
我该怎么做呢?
解决方案
不是 100% 清楚你想要什么;我猜你希望所有构造的值WrappedTwo
都被认为是等效的?
newtype ForgetOrder a = ForgetOrder a
instance Eq (ForgetOrder a) where
_ == _ = True
instance Ord (ForgetOrder a) where
compare _ _ = EQ
然后您可以将您的类型定义为:
data WrapperType = WrappedOne OrderedType
| WrappedTwo (ForgetOrder UnorderedType) deriving (Eq, Ord, Show)
是的,必须包装和打开新类型有点麻烦,并且编写模式同义词来避免它也很麻烦。这就是生活。
但是,我担心你也想要WrappedTwo Red /= WrappedTwo Green
。在这一点上,我将不得不与瓦格纳先生一起赶上潮流,并说,无论你正在穿越的思想路径需要这个,转身寻找另一种方式。Haskell 的一大乐趣是人们关心法律[1]。你会发现在 Hackage 上定义违法实例的库很少。并且有充分的理由:例如,Data.Set
期望Ord
定义一个总订单并与Eq
. 具有违法行为的类型Ord
使Set
该类型的 a 完全荒谬和破坏。但我自信地把各种东西放在Set
s 中,世界上没有任何担忧,因为合法性在 Haskell 文化中无处不在。
但是,如果您不这么认为……很好。抱歉说教。
[1] 我很尴尬地发现课程中没有记录Ord
预期的法律。无论如何,我对这些法律的传统理解如下:
等价符号:
x < y = compare x y == LT x > y = compare x y == GT x == y = compare x y == EQ x <= y = x < y || x == y x >= y = x > y || x == y
==
是等价关系:x == x If x == y then y == x If x == y and y == z then x == z
==
可扩展 性(这个似乎比其他的要宽松一些;例如,可能不是可扩展的sort
前提的文档):==
if x == y, then f x == f y
(对于可以从给定抽象边界之外定义的 f;IOW 允许相同值的不同表示,只要用户无法区分它们。)
总数
<
:If x <= y and y <= z then x <= z
(三分法来自“符号等价”和比较)
推荐阅读
- python - 对如何执行遥测的疑问:使用开发板和笔记本电脑
- excel - 在范围内使用 lastRow 进行更改功能
- c++ - 如何在编译期间为 C++ 预处理器指令定义值?
- oracle - 有没有一种简单的方法可以将 Windows 用户环境变量拉入 Oracle SQL 以用于输入密码?
- visual-studio - 部署后无法在 Azure 上加载 Vuejs 应用程序
- r - 如何在 R 中对具有 NA 的整个表应用 t 检验
- python-3.x - 没有名为“django_heroku”的模块
- python - How to create a random tensor with a given shape with the C++ Tensorflow API?
- php - How to map collection with incrementing inner array (for loop)
- node.js - TypeORM 外键未在查找调用中显示