Why do I need the amount GHC.Num.fromInteger?

I have a three-dimensional vector data type defined as 3 floats. I understand that if I provide a Num instance for my class and define normal math operators, I can use them in my class.

 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) 

When I upload my file to ghci, I get warnings because I did not define all the functions in Num , which makes sense.

 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. 

However, I can still use the ones I defined.

 *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} 

My confusion is due to the following error that I get when trying to use the sum function

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

Why does the amount need to determine fromInteger for my Vec3 data Vec3 ? First, I would suggest that the sum uses only the + function, and for another, my data type does not use Integer .

+6
source share
2 answers

Here, how the amount is implemented:

 sum = foldl (+) 0 

Note the literal 0 . Let it check in GHCi:

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

As it turned out, numeric literals are sugar for fromInteger . Those. 0 is actually fromInteger 0 .

Thus, sum requires fromInteger because the above definition is sugar for:

 sum = foldl (+) (fromInteger 0) 

The implementation fromInteger is simple:

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

In addition, I would highly recommend that when creating an instance always define it completely in order to avoid unforeseen troubles like this.

+9
source

What should be returned sum [] :: Vec3 ?


The sum function can be defined as

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

0 is actually fromInteger (0 :: Integer) , so you need fromInteger use sum .

Actually in base 4.8, sum is defined in terms of sum Monoid and Foldable , but this is a different story. You still need fromInteger (0 :: Integer) .

+4
source

All Articles