Since Haskell functions have only one argument, where the rest of arguments stay like lambdas, then we can do this:
foo a b = a + b -- this is like foo a = \b -> a + b
foo 1 2 -- ok
Well, I noticed that if I declare the function returning a lambda, just like in comment, the foo 1 2
will works fine the same way.
But when I compose these functions, like this:
foo a b = a + b
bar x = x * x
bar . foo 1 2 -- oh, it's wrong, I need do '(bar . foo 1) 2'
...This returns an error.
Ok, the question is: Why doesn't returning a lambda from function work like the function composition? I mean, in composition I need to put parentheses around the one, and no parentheses are needed when a lambda is returned from function.
Let's assume that you've define the following in GHCi:
λ> let foo a b = a + b
λ> let bar x = x * x
Based on some of your follow-up comments, it seems that you believe
bar . foo 1 2
to be equivalent to
(bar . foo 1) 2
However, remember that function application (space) has higher precedence than the composition operator (.
); therefore
bar . foo 1 2
is really equivalent to
bar . ((foo 1) 2)
Now, let's look at the types:
.
has type(b -> c) -> (a -> b) -> a -> c
; its two arguments are functions (that can be composed).bar
has typeNum a => a -> a
, and is therefore compatible with the type (b -> c
) of the first argument of.
.foo 1 2
has typeNum a => a
; it's a (polymorphic) numeric constant, not a function, and is therefore not compatible with the type (a -> b
) of the second argument of.
.
That's why you're getting a type error in bar . foo 1 2
. What you can do, though, is
bar $ foo 1 2
because the $
operator has type (a -> b) -> a -> b
. See Haskell: difference between . (dot) and $ (dollar sign)
bar . foo 1 2
is bar . (foo 1 2)
not (bar . foo 1) 2
There's nothing mysterious going on here related to lambdas. Say we expanded the application of foo
to 1:
bar . foo 1 2
bar . (\b -> 1 + b) 2
Now, we apply the lambda to the 2
bar . 3
And there is your problem.
Conversely, if we place the parentheses correctly, we evaluate it like this:
(bar . foo 1) 2
(bar . (\b -> 1 + b)) 2
(\x -> bar ((\b -> 1 + b) x)) 2
bar 3
来源:https://stackoverflow.com/questions/27547217/why-doesnt-haskell-accept-arguments-after-a-function-composition