Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell signatures: basics

Tags:

haskell

Why this does not work exactly?

sum :: (Num a, Num b) => a -> b -> c
sum a b = a + b

For sure, the error message is related to the signature but I continue to not understand the reason.

Couldn't match expected type ‘a’ with actual type ‘b’
‘b’ is a rigid type variable bound by
  the type signature for:
    sum :: forall a b c. (Num a, Num b) => a -> b -> c

‘a’ is a rigid type variable bound by
  the type signature for:
    sum :: forall a b c. (Num a, Num b) => a -> b -> c

In the second argument of ‘(+)’, namely ‘b’
In the expression: a + b
In an equation for ‘sum’: sum a b = a + b

What Am I missing?

like image 381
BigMeister Avatar asked Feb 03 '18 16:02

BigMeister


People also ask

What are type signatures in Haskell?

From HaskellWiki. A type signature is a line like. inc :: Num a => a -> a. that tells, what is the type of a variable. In the example inc is the variable, Num a => is the context and a -> a is its type, namely a function type with the kind * -> * .

Which function is used to find type signature in Haskell?

Since the type of elem y z is Bool , this matches with the function (&&) x , and thus the type of (&&) x (elem y z) is thus Bool .

What does B mean in Haskell?

In b Bool , b stands for a parametrized type that takes one type parameter (in Haskell parlance, b is a type constructor of kind * -> * ), such as Maybe , IO or [] .

Does order matter in Haskell?

There is no Order By the way, Haskell is a lazy language, so things are not evaluated in the order you write them. Instead they are evaluated when the values are needed.


2 Answers

Because the (+) function has signature:

(+) :: Num a => a -> a -> a

So that means that the (+) function requires the operands to have the same type, and the result has the same type as the operands.

Your signature would mean that a programmer can pick any Num type as first operand, and any Num type as second operand, and then construct any type. So it would mean that I could specialize the function into sum :: Int -> Float -> Char, but there is no such (+) defined.

We can make the type more flexible, for instance by using fromIntegral :: (Integral a, Num b) => a -> b:

integralSum :: (Integral i, Integral j, Num c) => i -> j -> c
integralSum x y = fromIntegral x + fromIntegral y
like image 156
Willem Van Onsem Avatar answered Oct 01 '22 19:10

Willem Van Onsem


For a different answer let's try ignoring everything besides the type signature.

sum :: (Num a, Num b) => a -> b -> c

This says that if I give you a value of some type and all you know is it is an instance of Num (the a type variable), and I give you a second value which could be a different type but also a Num (the b type variable), then you know how to give me a value of any type I ask for (c).

That is, I'm going to give you (3%4 :: Rational) and (7.99 :: Double) could you please give me val :: Config which is the configuration structure for my web server? The expression sum (3%4) 7.99 :: Config matches your type signature after all.

like image 38
Thomas M. DuBuisson Avatar answered Oct 01 '22 19:10

Thomas M. DuBuisson