简体   繁体   中英

Haskell: Why is ((.).(.)) f g equal to f . g x?

Could you please explain the meaning of the expression ((.).(.))? As far as I know (.) has the type (b -> c) -> (a -> b) -> a -> c.

(.) . (.) (.) . (.) is the composition of the composition operator with itself.

If we look at

((.) . (.)) f g x

we can evaluate that a few steps, first we parenthesise,

((((.) . (.)) f) g) x

then we apply, using (foo . bar) arg = foo (bar arg) :

~> (((.) ((.) f)) g) x
~> (((.) f) . g) x
~> ((.) f) (g x)
~> f . g x

More principled,

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

So, using (.) as the first argument of (.) , we must unify

b -> c

with

(v -> w) -> (u -> v) -> (u -> w)

That yields

b = v -> w
c = (u -> v) -> (u -> w)

and

(.) (.) = ((.) .) :: (a -> v -> w) -> a -> (u -> v) -> (u -> w)

Now, to apply that to (.) , we must unify the type

a -> v -> w

with the type of (.) , after renaming

(s -> t) -> (r -> s) -> (r -> t)

which yields

a = s -> t
v = r -> s
w = r -> t

and thus

(.) . (.) :: (s -> t) -> (u -> r -> s) -> (u -> r -> t)

and from the type we can (almost) read that (.) . (.) (.) . (.) applies a function (of one argument) to the result of a function of two arguments.

You've got an answer already, here's a slightly different take on it.

In combinatory logic (.) is B -combinator : Babc = a(bc) . When writing combinator expressions it is customary to assume that every identifier consists of one letter only, and omit white-space in application, to make the expressions more readable. Of course the usual currying applies: abcde is (((ab)c)d)e and vice versa.

(.) is B , so ((.) . (.)) == (.) (.) (.) == BBB . So,

BBBfgxy = B(Bf)gxy = (Bf)(gx)y = Bf(gx)y = (f . g x) y    
 abc        a  bc                 a b  c                  

We can throw away both y s at the end (this is known as eta-reduction : Gy=Hy --> G=H , if y does not appear inside H 1 ). But also, another way to present this, is

BBBfgxy = B(Bf)gxy = ((f .) . g) x y = f (g x y)     -- (.) f == (f .)
-- compare with:       (f .) g x = f (g x)

((f .) . g) xy might be easier to type in than ((.).(.)) fgxy , but YMMV.


1 For example, with S combinator , defined as Sfgx = fx(gx) , without regard for that rule we could write

Sfgx = fx(gx) = B(fx)gx = (f x . g) x
Sfg = B(fx)g = (f x . g)   --- WRONG, what is "x"?

which is nonsense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM