问题描述
一些戒指可以配备一个标准功能: class(Ring.C a)=> EuclideanDomain a where
norm :: a - >整数
有了这个函数,戒指可以按照明显的顺序排列:
compare xy = compare(norm x)(norm y)
但我不确定如何表明这一点。我试图做到这一点:(b)
$ b
instance(EuclideanDomain a,Eq a)=> Ord a其中
但这给了我一些警告,当我启用相关的编译器标志时,它告诉我约束不小于实例头 - 如果启用UndecidableInstances,一切都会到地狱。
有没有办法做我想做的事?
hammar已经提供了解决方案;我想指出这个例子的另一个问题。你想表达的是每当一个类型是 Eq
和 EuclideanDomain
的一个实例时,使用这个规则来创建一个 Ord
的实例。但这在Haskell中是不可压缩的。该行
instance(EuclideanDomain a,Eq a)=> Ord a其中
其实意味着,使用此规则来制作 Ord
实例,如果 EuclideanDomain
和 Eq
的实例不在范围。这是不好的,因为这个规则将与其他Ord实例重叠。
基本上任何时候你想写一个实例 class typevar
,你将需要一个新类型。
Some rings can be equipped with a norm function:
class (Ring.C a) => EuclideanDomain a where
norm :: a -> Integer
With this function, the ring can be ordered in the obvious way:
compare x y = compare (norm x) (norm y)
But I'm not sure how to indicate this. I tried to do
instance (EuclideanDomain a, Eq a) => Ord a where
but this gives me some warnings, and when I enable the relevant compiler flags it tells me "Constraint is no smaller than the instance head" - if I enable UndecidableInstances everything goes to hell.
Is there a way to do what I want?
hammar's already provided a solution; I'd like to point out another problem with this example. What you want to express is "Whenever a type is an instance of Eq
and EuclideanDomain
, use this rule to make an instance for Ord
." But this is inexpressible in Haskell. The line
instance (EuclideanDomain a, Eq a) => Ord a where
actually means, "Use this rule to make an Ord
instance for any type. It's an error if instances of EuclideanDomain
and Eq
aren't in scope". That's not good, because this rule will overlap with every other Ord instance.
Basically any time you want to write an instance Class typevar
, you're going to need a newtype.
这篇关于Haskell约束不小于实例头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!