问题
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?
回答1:
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 $.
来源:https://stackoverflow.com/questions/57544489/why-is-there-infinite-recursion-when-i-apply-a-function-with-the-argument-n-1-n