I am a beginner in Haskell and have a problem with the def of functions in Haskell. Values are functions in Haskell, right? (+3) 3 = 6 but what does (+3) (+3) mean. Does (+3) counts as an value ?
2 Answers
(+3) isn't what you probably think it is. In other languages, this means the numerical value positive‑three. In Haskell it's the partial application of the + operator, and is a function taking one argument (the other number to add). It adds three to whatever it's given. So (+3) x is the application of the function (+3) to the value x and returns x+3. However, (+3) (+3) tries to add 3 to the function (+3) which doesn't make sense and gives a type error.
It might help to imagine replacing + with a regular function called plus:
plus x y = y + x
Then, (+3) is equivalent to plus 3, and (+3) 3 to (plus 3) 3 which is the same as plus 3 3. However, (+3) (+3) is equivalent to (plus 3) (plus 3) or plus 3 (plus 3) which doesn't make sense.
You might want to think about what (+3) . (+3) means. This chains together two applications of adding three, and is a single-argument function that adds six.
Comments
(+3) (+3) is simply a type error and, therefore, it won't compile.
The type of (+3) is Int -> Int, which means that when applying an Int, we get another Int. It also means that you can only apply values of type Int!
So, you can't apply to (+3) a value of type Int -> Int, only values of type Int.
So yes, (+3) is value, but not of the right type to apply it to a function that expects a value of type Int.
Int can't be unified with Int -> Int because they have different type constructor, which makes them different types, as pointed out by @DanielWagner. The outermost constructor of Int -> Int is -> while the outermost constructor of Int is simply Int. It is sufficient that two types have different outermost constructor for considering them different.
10 Comments
(.) is (b -> c) -> (a -> b) -> a -> c, which is the same as (b -> c) -> (a -> b) -> (a -> c). It makes sense, function compositions, takes 2 functions and returns a function. The type of foldr is (a -> b -> c) -> b -> [a] -> b. To remove ambiguity, lets rename the type variables to this: foldr :: (fa -> fb -> fb) -> fb -> [fa] -> fb. (.) :: (cb -> cc) -> (ca -> cb) -> (ca -> cc). Then, it's clear that the application foldr (.) has this type: (ca -> cb) -> [cb -> cb] -> (ca -> cb). Also: (.) :: x -> x. and finally, foldr (.) idis: [x -> x] -> (x -> x).(cb -> cc) can be unified with type variables like fa; what I did was to exactly replace all fas with (cb -> cc). And something similar for fb&(ca->cb).a=(x -> y) and b=(x -> z) and you unify a with b then, that unification will force y=z. That is why we ended with only 1 type variable, x; because the unifications that where done forced to all type variables to belong to the same type.Int -> Int does not have kind * -> *; it has kind *, just like Int. But the outer-most (type) constructor of Int -> Int is (->), while the outer-most constructor of Int is Int, and only type with the same outer-most constructor may unify.
(+3) (+3)won't work, unless you've madea -> aaNuminstance. That being said, if you're interested in definitions, you should have a look at the Haskell report.