2013-04-27 61 views
3

我試圖瞭解在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

只要在該文件的頂部添加一個'{ - #LANGUAGE FlexibleInstances# - }'編譯指示,它就可以很好地編譯 – 2013-04-27 17:49:58

+0

但編譯器在抱怨什麼? – me2 2013-04-27 17:51:58

+0

http://hackage.haskell.org/trac/haskell-prime/wiki/FlexibleInstances – 2013-04-27 17:56:11

回答

5

你只是碰到了Haskell標準的限制。標準Haskell只允許restricted set of instance declarations。特別是所有實例必須是「簡單的」,因爲它們是應用於零個或更多類型變量的類型。

這意味着您可以有Int,MaybeMaybe a的實例。但是,您不能有一個例如Maybe Int。這就是你遇到的問題:你的實例有一個類型(->)適用於Int以及一個變量。

但是,儘管此行爲不符合標準,但它仍然有意義,因此您可以使用擴展名啓用它。這就是FlexibleInstances所做的,明顯的警告是你的代碼不再是標準的Haskell。

3

在標準Haskell中,例如頭端(在一個實例類名之後的部分)都必須是這樣的形式,其中T a1 a2 .. anT類型構造和ai是不同類型的變量。

編譯器抱怨,因爲你的實例頭是(->) Int r,並且Int不是一個類型變量。

在GHC中,這個限制可以使用FlexibleInstances擴展來解除,唯一的缺點是可能缺少可移植性。