2015-07-12 36 views
6

我有一個三維矢量數據類型定義爲3浮點數。我知道如果我爲我的課程提供一個Num實例並定義正常的數學運算符,我可以在課堂上使用它們。爲什麼總和需要GHC.Num.fromInteger?

data Vec3 = Vec3 { x :: Float 
       , y :: Float 
       , z :: Float 
       } deriving (Show, Eq) 

instance Num Vec3 where 
    (+) v1 v2 = Vec3 (x v1 + x v2) (y v1 + y v2) (z v1 + z v2) 

當我將文件加載到ghci中,我得到警告,因爲我沒有Num定義所有的功能,這是有道理的。

Prelude> :l temp.hs 
[1 of 1] Compiling Main    (temp.hs, interpreted) 

temp.hs:6:10: Warning: 
    No explicit method or default declaration for `*' 
    In the instance declaration for `Num Vec3' 

temp.hs:6:10: Warning: 
    No explicit method or default declaration for `abs' 
    In the instance declaration for `Num Vec3' 

temp.hs:6:10: Warning: 
    No explicit method or default declaration for `signum' 
    In the instance declaration for `Num Vec3' 

temp.hs:6:10: Warning: 
    No explicit method or default declaration for `fromInteger' 
    In the instance declaration for `Num Vec3' 
Ok, modules loaded: Main. 

但是,我仍然可以使用我定義的那些。想爲什麼和需要fromInteger定義爲我的Vec3數據類型使用SUM函數

*Main> sum [a,b] 
Vec3 {x = *** Exception: temp.hs:6:10-17: No instance nor default method for class operation GHC.Num.fromInteger 

*Main> let a = Vec3 1.0 2.0 3.0 
*Main> let b = Vec3 2.0 4.0 5.0 
*Main> a + b 
Vec3 {x = 3.0, y = 6.0, z = 8.0} 

我的困惑來自於以下幾個錯誤我得到什麼?首先,我會認爲這筆款項只使用+函數,而另一方面,我的數據類型不使用Integer

+0

在將數據類型視爲類的實例之前,應始終在最小完整定義中定義** all **操作... – Bakuriu

+2

這裏真正的問題在於,即使向量不是數字,您也會使'Vec3'成爲'Num'的一個實例。 – rightfold

+0

要擴展@rightfold - 不要僅僅因爲你想要+向量而創建Num的實例,即使向量上使用的某些操作符傾向於與數字操作符具有相同的名稱,向量也不是數字。 (儘管你可以將矢量當作數字來處理,如果用'矢量',你只是指「固定大小的數字集合」,而不是幾何或物理意義上的矢量)。 – Cubic

回答

9

這裏的總和是如何實現的:

sum = foldl (+) 0 

通知的字面0。讓我們來看看它在GHCI鍵入:

λ> :t 0 
0 :: Num a => a 

事實證明,數字文字是糖fromInteger。即,0實際上是fromInteger 0

因此,sum需要fromInteger,因爲上面的定義是糖:

sum = foldl (+) (fromInteger 0) 

fromInteger實現很簡單:

instance Num Vec3 where 
    fromInteger n = let a = (fromInteger n) in Vec3 a a a 

此外,我會強烈建議,每當做一個實例時,總要定義它以避免這樣的無法預料的麻煩。

+1

這很有道理。切線問題,但我在哪裏可以找到這些常用函數的實現?我試過看,但不知道在哪裏看 – user3288829

+0

@ user3288829 https://www.haskell.org/hoogle/?hoogle=sum – phadej

+0

@ user3288829源文件是['GHC.Num'](https:// hackage.haskell.org/package/base-4.7.0.2/docs/src/GHC-Num.html)。 – AJFarmar

4

sum [] :: Vec3應該返回什麼?


sum功能可以定義爲

sum :: (Num a) => [a] -> a 
sum = foldl (+) 0 

0居然有fromInteger (0 :: Integer),因此你需要fromInteger使用sum

在實際上基4.8 sumSumMonoidFoldable來定義的,但這是不同的故事。那裏你還需要fromInteger (0 :: Integer)