我试图理解this question给出的关于可变参数函数的示例,并试图修改代码:
class SumRes r where
sumOf :: Integer -> r
instance SumRes Integer where
sumOf = id
instance (Integral a, SumRes r) => SumRes (a -> r) where
sumOf x = sumOf . (x +) . toInteger
到此:
class SumRes r where
sumOf :: Int -> r
instance SumRes Int where
sumOf = id
instance (SumRes r) => SumRes (Int -> r) where
sumOf x = sumOf . (x +)
我得到Illegal instance declaration for SumRes (Int -> r)
。有人可以解释这意味着什么,我反对的约束是什么?
答案 0 :(得分:5)
你刚刚遇到Haskell标准的限制。标准Haskell只允许restricted set of instance declarations。特别是所有实例都必须是“简单的”,因为它们是应用于零个或多个类型变量的类型。
这意味着您可以拥有Int
,Maybe
或Maybe a
的实例。但是,无法拥有Maybe Int
之类的实例。这就是您遇到的问题:您的实例具有应用于->
的类型(Int
)以及变量。
但是,尽管此行为不符合标准,但它仍然有意义,因此您可以使用扩展名启用它。这就是FlexibleInstances
所做的,显而易见的是你的代码不再是标准的Haskell了。
答案 1 :(得分:3)
在标准Haskell中,实例头(实例中类名后面的部分)必须是T a1 a2 .. an
形式,其中T
是类型构造函数,ai
是不同的类型变量。
编译器抱怨,因为您的实例头是(->) Int r
,而Int
不是类型变量。
在GHC中,可以使用FlexibleInstances
扩展来解除此限制,这样做的唯一真正缺点是可能缺乏可移植性。