HastatusXXI
HastatusXXI

Reputation: 101

Different types in sum function

I'm new to Haskell so this could be a stupid question. I'm reading a book where it says :type sum is supposed to show sum :: (Num a) => [a] -> a. Instead of that the message is sum :: (Num a, Foldable t) => t a -> a. As I've seen in https://www.haskell.org/hoogle/?hoogle=Sum this difference is due to -I think- the existence of two different sum functions. Maybe it's something like polymorphism in Java, I'm just starting and I have no idea about how Haskell works.

So my questions are: how could I use the sum function which type is sum :: (Num a) => [a] -> a instead of the other one? Could you explain me what's going on here?

Upvotes: 1

Views: 1361

Answers (1)

duplode
duplode

Reputation: 34398

As I've seen in https://www.haskell.org/hoogle/?hoogle=Sum this difference is due to -I think- the existence of two different sum functions. Maybe it's something like polymorphism in Java

It is, indeed, polymorphism, though not in this way (see the P.S. at the end of this answer). Note that...

sum :: (Num a) => [a] -> a

... is already polymorphic in the type of the numbers being summed, so it would work with, for instance, lists of Integer and lists of Double. The difference between that and...

sum :: (Num a, Foldable t) => t a -> a

... is that this sum is also polymorphic in the type of the container:

GHCi> -- +t makes GHCi print the types automatically.
GHCi> :set +t
GHCi> sum [1 :: Integer, 2, 3]
6
it :: Integer
GHCi> sum [1 :: Double, 2, 3]
6.0
it :: Double
GHCi> import qualified Data.Set as S
GHCi> :t S.fromList
S.fromList :: Ord a => [a] -> S.Set a
GHCi> sum (S.fromList [1 :: Double, 2, 3])
6.0
it :: Double

For a container type to be used with sum, it has to have an instance of the Foldable class, which covers functions that, like sum, might be expressed as flattening the container into a list and then folding it in some way.

P.S.: Your book says something different than what you have seen because until quite recently the sum function in the Prelude used to have the less general, list-specific type, and your book predates the change. Having two different functions called sum, even if one is strictly more general than the other, would lead to a name clash (it was for a similar reason that I imported the Data.Set module qualified in the example above -- it is a good idea to do so because it defines a few functions such as map that clash with Prelude functions, and qualifying them with, say, S.map avoids any issues).

Upvotes: 2

Related Questions