这很好用:
class YesNo a where
yesNo :: a-> Bool
instance YesNo Bool where
yesNo True = True
yesNo _ = False
instance YesNo [a] where
yesNo [] = False
yesNo _ = True
instance YesNo (Maybe a) where
yesNo Nothing = False
yesNo _ = True
但我收到代码错误:
instance (Num a) => YesNo a where -- error is here
yesNo 0 = False
yesNo _ = True
异常消息:
ghci> :l src
[1 of 1] Compiling Main ( src.hs, interpreted )
src.hs:16:21:
Illegal instance declaration for `YesNo a'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
In the instance declaration for `YesNo a'
Failed, modules loaded: none.
ghci>
我做错了什么?
答案 0 :(得分:5)
您似乎正在努力使其成为Num
实例的每个类型自动成为YesNo
的实例。
不幸的是,你不能这样做。
您只能为特定类型声明实例。因此,您可以为Int
或Double
声明一个实例,但是您无法为每个Num
"声明一个实例。
答案 1 :(得分:2)
正如错误消息已经指出的那样,有ghc
个选项可以使您的实例声明完全合法(但是,如果您的ghc是{{3,则必须向其添加约束Eq a
}})
ghci -XFlexibleInstances -XUndecidableInstances <your program>
将以您期望的方式编译和工作。
为什么默认情况下不允许使用灵活且不可判定的实例?
类型类 open ,可以在以后扩展。假设其他人会使用Num
扩展instance (Num a) => Num [a])
,例如fromInt x = [fromInt x]
和组件添加等。然后我们会有重叠的实例:shoud yesNo [0]
为{{1} }或True
?因此,通过扩展一个类(False
),其他类(Num
)的实例突然重叠。这就是默认情况下不允许使用灵活实例的原因
声明YesNo
时,instance (Eq a, Num a) => YesNo a
并不比Num a
严格更小(更简单)。我和你知道检查YesNo a
- ness的任何类型最终会产生一个aswer,但是再想一想,其他人(为什么不呢?)会添加一个实例YesNo
。然后类型检查器会陷入循环:(YesNo a) => Num a where..
这就是默认情况下不允许(可能)不可判定的实例的原因
因此,覆盖类型类定义的默认限制现在可能很有效,但将来会引起严重的搔痒。
答案 2 :(得分:1)
试试这个:
instance (Num a) => YesNo a where
yesNo x | x == fromIntegral 0 = False
| otherwise = True
问题是0
不属于a
类型。
但是,在Num
的任何情况下,您都必须定义fromIntegral
函数。