2012-08-22 230 views
18

我要定義一個操作(稱之爲+-+),在這個作品:運算符重載

if a,b are Char => a +-+ b = [a][b] 
if a,b are Integer => a +-+ b = a+b 

我嘗試:

class Summable a where 
    (+-+)  :: a -> a -> b 

instance Summable Integer where 
    a +-+ b  = a + b 

instance Summable Char where 
    a +-+ b  = [a] ++ [b] 

,但我得到的錯誤:

Couldn't match type `b' with `Integer'.... 
Couldn't match type `b' with `[Char]' .... 

可以做到這一點嗎?怎麼樣?

+1

請注意''[a] ++ [b]'只是'[a,b]'... –

回答

25

問題是類型變量b無法從實例中確定,即使它是固定的。 (有這樣一個自由變量需要該函數返回任何類型的東西,即undefined。)

你可以給+-+的類型a -> a -> a?如果是這樣,那就做。 (但看起來像這是不可能的。)

否則,您可以使用functional dependencies,以便實例指定結果類型或type families,以便實例化的其中一個屬性是結果類型。

對於函數依賴,代碼可能看起來像:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} 

class Summable a result | a -> result where 
    (+-+) :: a -> a -> result 

instance Summable Char String where 
    a +-+ b = [a] ++ [b] 

instance Summable Integer Integer where 
    a +-+ b = a + b 

對於類型的家庭,這將是這樣的:

{-# LANGUAGE TypeFamilies #-} 

class Summable a where 
    type Result a 
    (+-+) :: a -> a -> Result a 

instance Summable Char where 
    type Result Char = String 
    a +-+ b = [a] ++ [b] 

instance Summable Integer where 
    type Result Integer = Integer 
    a +-+ b = a + b 

(謝謝維斯特和弗拉基米爾Matveev用於固定各種錯誤我做了!:))