Sorry this is worded poorly, but it's hard to describe.
I guess I'll just jump to the example:
add :: Integer -> Integer -> Integer
add x y = x + y
why is it:
:: Integer -> Integer -> Integer
instead of:
:: Integer, Integer -> Integer
the arrow is the "Function type-mapping operator", not some kind of separator, no?
(->) is often called the "function arrow" or "function type constructor", and while it does have some special syntax, there's not that much special about it. It's essentially an infix type operator. Give it two types, and it gives you the type of functions between those types.
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 * -> * .
Because of currying. Think about the type of this:
add 3 :: Integer -> Integer
If you give add
one number it returns a function that maps an Integer
to another integer. So you could do this:
map (add 3) [1..10]
It doesn't make sense to treat arguments differently from return types with partial application.
EDIT to clarify
I think bheklilr makes a good point that the type signature can be read like this
add :: Integer -> (Integer -> Integer)
We can take a function with more arguments, zipWith3
because it is the only one I can really think of.
zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
If we just read what this does it takes a function that takes 3 values and returns a fourth and then 3 lists of those values respectively and it returns a list of the fourth value. Trying it out.
add3 :: Int -> Int -> Int -> Int
add3 a b c = a + b + c
Prelude>zipWith3 add3 [1] [2] [3]
[6]
Although, in this case all the values are of type Int
it still demonstrates the point.
Now what if we don't give it all the lists? What if we give it no lists just add3
.
zipWith3 add3 :: [Int] -> [Int] -> [Int] -> [Int]
zipWith3 add3 :: [Int] -> ([Int] -> [Int] -> [Int])
zipWith3 add3 :: [Int] -> [Int] -> ([Int] -> [Int])
So, now we have a function that takes 3 lists and returns a list. But this is also a function that takes a list are returns a function that takes 2 lists and returns a list. There is no way to distinguish between them really.
(zipWith3 add3) [1,2] [3,4] [5,6] :: [Int]
(zipWith3 add3) [1,2] :: [Int] -> [Int] -> [Int]
See where I'm going with this? There is no distinction between arguments are return types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With