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

后端 未结 2 1904
轻奢々
轻奢々 2021-01-22 16:23

Considering Haskell has currying functions, we can do this:

foo a b = a + b -- equivalent to `foo a = \\b -> a + b`

foo 1 -- ok, returns `\\b -> 1 + b`
fo         


        
相关标签:
2条回答
  • 2021-01-22 17:01

    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
    
    0 讨论(0)
  • 2021-01-22 17:03

    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)

    0 讨论(0)
提交回复
热议问题