如何为另一个类型的类中的所有类型编写实例? [英] How to write an instance for all types in another type class?
问题描述
我必须定义一个类型类 Truthy
,其中包含一个方法 true
,将类型的实例转换为 Bool
值。
我的类型声明:
class Truthy a where
true :: a - > Bool
接下来,我必须为各种类型定义此类的实例,包括列表和数字类型。我已经完成了列表和 Int
s,但是是否有办法一次执行所有数字类型?
实例Truthy Int其中
true =(/ =)0
我曾尝试添加类型约束,但它不起作用:
instance(Num a)=> (Truthy a)其中
true =(/ =)0 :: a
是一种做法,类似于我的想法,或者我应该为每个数字类型单独定义它?
这可能对家庭作业没有帮助,但你实际上可以写出这样的声明。您只需启用 -XFlexibleInstances
即可。至少在GHC中,您可以通过在文件顶部添加一个附注来实现:
{ - #LANGUAGE FlexibleInstances# - }
如果仔细观察您收到的错误消息,它会说使用-XFlexibleInstances 。
在这种特殊情况下,您还需要启用 UndecideableInstances
和 OverlappingInstances
:
{ - #LANGUAGE FlexibleInstances,UndecideableInstances,OverlappingInstances# }
您需要 FlexibleInstances
,因为标准Haskell会不允许任何形式的类型变量在头部出现多次。这是完全正确的 - 我是最常用的扩展之一(根据这个问题<您需要 UndecideableInstances
,因为您的实例声明可能会导致类型检查器永远循环。
UndecideableInstances
可以通过限制它在尝试减少实例时检查的深度来防止这种情况。这通常是 - 包括在这种情况下 - 很好,但理论上可以确定特定程序是否通过了类型检查实现依赖。哈马尔指出,您需要启用 OverlappingInstances
,因为在检查它们是否重叠时,实例的上下文被忽略。在这种情况下,上下文是 Num a
位。因此,用于检查它是否重叠的实例被读为实例Truthy a ...
,并与所有内容重叠。使用 OverlappingInstances
启用,您只需要一个最特定的实例即可运行。 I have to define a type class Truthy
wich contains a method true
converting an instance of the type class to a Bool
value.
My type class declaration:
class Truthy a where
true :: a -> Bool
Next, I have to define instances of this class for various types, including list and numeric types. I have done it for lists and Int
s, but is there a way to do it for all numeric types at once?
Based on my Int declaration:
instance Truthy Int where
true = (/=) 0
I have tried adding type class constraint, but it does not work:
instance (Num a) => (Truthy a) where
true = (/=) 0::a
If there is a way to do this similar to what I had in mind, or should I just define it for each numeric type separately?
This might not help for homework, but you actually can write a declaration like that. You just have to enable -XFlexibleInstances
to do so. At least in GHC, you can do this by putting a pragma at the top of your file:
{-# LANGUAGE FlexibleInstances #-}
If you look closely at the error message you got, it said something like "Use -XFlexibleInstances if you want to disable this.".
In this particular case, you would also need to enable UndecideableInstances
and OverlappingInstances
:
{-# LANGUAGE FlexibleInstances, UndecideableInstances, OverlappingInstances #-}
You need FlexibleInstances
because standard Haskell does not allow instances in any form where the type variable appears more than once in the head. This is completely fine--I it is one of the most common extensions used (as per this question).
You need UndecideableInstances
because your instance declaration could potentially cause the type checker to loop forever. I think using UndecideableInstances
prevents this by limiting how deeply it will check when trying to reduce the instance. This is usually--including in this case--fine, but could theoretically make whether a particular program passes the type checks implementation dependent. Still, it should work in your case.
As hammar pointed out, you need to enable OverlappingInstances
because the "context" of the instance is ignored when checking whether they overlap. The context is the Num a
bit in this case. So the instances--for checking if it overlaps--is read as instance Truthy a...
and overlaps with everything. With OverlappingInstances
enabled, you just need to have one instance that is the most specific for this to work.
这篇关于如何为另一个类型的类中的所有类型编写实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!