Haskell Variadic功能&实例声明

时间:2013-04-27 17:44:33

标签: haskell types

我试图理解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)。有人可以解释这意味着什么,我反对的约束是什么?

2 个答案:

答案 0 :(得分:5)

你刚刚遇到Haskell标准的限制。标准Haskell只允许restricted set of instance declarations。特别是所有实例都必须是“简单的”,因为它们是应用于零个或多个类型变量的类型

这意味着您可以拥有IntMaybeMaybe a的实例。但是,无法拥有Maybe Int之类的实例。这就是您遇到的问题:您的实例具有应用于->的类型(Int)以及变量。

但是,尽管此行为不符合标准,但它仍然有意义,因此您可以使用扩展名启用它。这就是FlexibleInstances所做的,显而易见的是你的代码不再是标准的Haskell了。

答案 1 :(得分:3)

在标准Haskell中,实例头(实例中类名后面的部分)必须是T a1 a2 .. an形式,其中T是类型构造函数,ai是不同的类型变量。

编译器抱怨,因为您的实例头是(->) Int r,而Int不是类型变量。

在GHC中,可以使用FlexibleInstances扩展来解除此限制,这样做的唯一真正缺点是可能缺乏可移植性。