2015-02-10 43 views
1

爲什麼ab之間的關係是不可扣除的?不可推導的關係

class Vector a where 
    (<.>) :: Num b => a -> a -> b 

data Vec2 a 
    = Vec2 (a, a) 

    deriving Show 

instance Num a => Vector (Vec2 a) where 
    Vec2 (a, b) <.> Vec2 (c, d) = a * c + b * d 

我想有一個Vec2代數數據結構,其中組件可以是任何數字。上述

+2

[Here](http://hackage.haskell.org/package/vector-space-0.8.7/docs/Data-VectorSpace.html)是向量空間類的標準實現。正如你會看到它使用'Scalar'作爲相關類型的家族,就像Ørjan所建議的那樣。 ('<.>'類實際上是一個子類,['InnerSpace'](http://hackage.haskell.org/package/vector-space-0.8.7/docs/Data-VectorSpace.html#t:InnerSpace) :並非所有的向量空間都允許標量/內積;它們都允許的只是將向量與標量相乘('* ^')並將向量相加(來自'添加劑組')的'^ + ^')。 – leftaroundabout 2015-02-10 23:45:49

回答

7
(<.>) :: Num b => a -> a -> b 

意味着(<.>)能產生任何型號的該函數的調用者可能希望。

例如,如果x,yVec2 Double,則可以調用x <.> y以返回Integer。然後編譯器會抱怨在發佈實例中的實現不夠普遍,因爲它返回Double而不是任何類型的調用者可能會選擇。

我認爲這不是代碼意圖建模的內容。

您可能需要切換到多參數類(你將需要啓用了一些擴展,GHC會告訴你哪些):

class Vector a b where 
    (<.>) :: a -> a -> b 

instance Num a => Vector (Vec2 a) a where 
    Vec2 (a, b) <.> Vec2 (c, d) = a * c + b * d 

由於現在的編譯器不能確定的x <.> y類型從x,y類型,您可能要添加使用

class Vector a b | a -> b where 
    (<.>) :: a -> a -> b 

或交替使用類型家庭

函數依賴
2

由於@ chi的回答說,你的代碼不會使b取決於a。要得到什麼,我想你想,你可以使用相關類型的家庭:

{-# LANGUAGE TypeFamilies #-} 

class Vector a where 
    type Element a 
    (<.>) :: a -> a -> Element a 

data Vec2 a 
    = Vec2 (a, a) 

    deriving Show 

instance Num a => Vector (Vec2 a) where 
    type Element (Vec2 a) = a 
    Vec2 (a, b) <.> Vec2 (c, d) = a * c + b * d 

另一種方法是使用多參數類型類有功能性依賴,但我認爲這是更復雜在這裏。