Reputation: 13
I have a Haskell function:
sumSquareOrSquareSum' :: (Num a, Ord a) => a -> a -> a
sumSquareOrSquareSum' x y = (\sumSquare squareSum ->
if sumSquare > squareSum
then sumSquare
else squareSum) (x^2 + y^2) (x+y)^2
If I run it as sumSquareOrSquareSum' 1 2
I get the answer 25
instead of the 9
I would expect.
If I make both branches return squareSum
I get 9
, if both return sumSquare
I get 25
. If I make the GT a LT I get 9
, so it appears to be the first term that's evaluating weirdly, or at least in a manner that I don't understand.
I can fix the problem by putting parentheses around the (x+y)^2
term making the final line:
else squareSum) (x^2 + y^2) ((x+y)^2)
So, I know how to fix it, but I'm not at all clear as to why there is a problem in the first place. Any insight would be appreciated.
Upvotes: 1
Views: 53
Reputation: 2411
Function application binds more tighly than operators, so
f x^2
is evaluated as
(f x)^2
instead of the
f (x^2)
you expect. This still applies to functions with two parameters, so
max a b^2
is actually
(max a b)^2
Flip the parameters like max b^2 a
and see the error message as haskell is trying to interpret that as (max b)^(2 a)
.
Upvotes: 2
Reputation: 477462
It is interpreted as:
sumSquareOrSquareSum' :: (Num a, Ord a) => a -> a -> a
sumSquareOrSquareSum' x y = ((\sumSquare squareSum ->
if sumSquare > squareSum
then sumSquare
else squareSum) (x^2 + y^2) (x+y))^2
So you square the result of the maximum of the sum of squares, and the sum. So you passed (x^2 + y^2)
as first parameter (1*1+2*2
is 5
) , and the sum (1+2
is 3
) as second parameter. This is thus returns 5
, and then we square it, so 25
.
You thus returned the square of the maximum of the sum of squares and the sum.
Upvotes: 1