开发者

haskell type signature question

Can someone explain me, why do these functions have different number of arguments and behavior, but the same type signature, yet they are both correct?

comp1 :: (a -> b) -> (b -> c) -> a -> c
comp1 f g = g.f

comp2 :: (a -> b) -> (b -> c) -> a -> c
comp2 f g x = g (f x)

also, why does comp2 has

comp2 :: (a -> b) -> (b -> c) -> a -> c

instead of something like

comp2 :: a -> (a 开发者_StackOverflow-> b) -> (b -> c) -> a -> c

?

Thank you.


comp2 f g x = g (f x)

is syntactic sugar for

comp2 = \f -> \g -> \x -> g (f x)

Similarly

comp1 f g = g.f

is sugar for

comp1 = \f -> \g -> g.f

The definition of . is:

f1 . f2 = \x -> f1 (f2 x) -- Names of arguments have been changed to avoid confusion

So if we insert the definition into the desugared form of comp1, we get:

comp1 = \f -> \g -> \x -> g (f x)

This is exactly the same as the desugared form of comp2, so clearly the definitions are equivalent.


comp1 f g = g.f is written in point-free style (not referring to points, but to values). When you call comp1, there is implicitly a third parameter being passed to g.f, which is the composition of the two functions g and f: (g.f) x equals g (f x), i.e. g is passed the result of f x. No parameter x exists in comp1 because it's implicitly passed to the function. (You could think of comp1 as a partially applied or curried function if it makes you feel better.)

comp2's type asks for two functions, one from (a->b) and another (b->c), as well as a parameter of type a. There is no need to put an a -> in its signature.

The two functions are really equivalent; one simply uses some Haskell tricks to be more concise.


Currying. A multi-argument function in ML and Haskell, is just syntactic sugar for a one-argument function that returns a function; the function that it returns takes the remaining arguments.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜