Why doesn't Haskell accept arguments after a function composition?

元气小坏坏 提交于 2019-12-02 06:18:51

问题


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.


回答1:


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 type Num a => a -> a, and is therefore compatible with the type (b -> c) of the first argument of ..
  • foo 1 2 has type Num 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)




回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!