Reputation: 3494
Here I can pass to function f
the argument 7-1
, without parentheses.
Prelude> f = (+1)
Prelude> f 7-1
7
1. Why is the following an infinite recursion?
Prelude> addRec :: (Eq a, Num a) => a -> a; addRec 0 = 0; addRec n = n + addRec n-1;
Prelude> addRec 5
2.
I can fix it by either adding parentheses to n-1
Prelude> addRec :: (Eq a, Num a) => a -> a; addRec 0 = 0; addRec n = n + addRec (n-1);
3.
Or by using the $
operator with parentheses on the whole addRec
recursion term:
Prelude> addRec :: (Eq a, Num a) => a -> a; addRec 0 = 0; addRec n = n + (addRec $ n-1)
I'd like to understand exactly how each expression works or doesn't work.
Here is my line of reasoning:
In addRec n = n (...)
we are effectively composing two function (without using the .
composition operator). We are composing (+)
and addRec
. Is Haskell in this example understanding we have a third function (-)
?
We are using function application (which as far as I understand is the operator represented by a whitespace after a function) to achieve this composition.
Function application is left associative, so my first question is: what does addRec n = n + addRec n-1
look like when we add the parentheses corresponding to the default left associativity?
Upvotes: 2
Views: 132
Reputation: 80805
f 7-1
doesn't mean what you think it means.
In Haskell, function application has the highest priority. This means that f 7-1
is always interpreted as (f 7) - 1
. The absence of a space around the minus sign is irrelevant, and it is only by coincidence that you get the correct answer: f 7 = (+ 1) 7 = 8
, and then 8 - 1 = 7
. This would not happen if your function was defined as f = (* 2)
.
Similarly, addRec n-1
is interpreted as (addRec n) - 1
, thus calling addRec
with the same argument n
every time, producing infinite recursion.
The two ways to fix it, you already know: parens or operator $
.
Upvotes: 11