Haskell: Why ((.... (.)) F g equals f. gx?

Could you explain the meaning of the expression ((.). (.))? As far as I know (.) It has type (b β†’ c) β†’ (a β†’ b) β†’ a β†’ c.

+8
types haskell function-composition combinators pointfree
source share
2 answers

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

If we look at

 ((.) . (.)) fgx 

we can appreciate that a few steps, first in parentheses,

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

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

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

More principled,

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

So, using (.) As the first argument (.) , We have to combine

 b -> c 

from

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

This gives

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

and

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

Now, to apply this to (.) , We need to unify the type

 a -> v -> w 

with type (.) after renaming

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

what gives

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

and therefore

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

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

+22
source share

You already have an answer, here is a slightly different matter.

In combinational logic (.) B -combinator : Babc = a(bc) . When writing combinatorial expressions, it is generally accepted that each identifier consists of only one letter and omits the space in the application to make the expressions more readable. Of course, conventional currying applies: abcde is (((ab)c)d)e and vice versa.

(.) B , therefore ((.) . (.)) == (.) (.) (.) == BBB . Thus,

 BBBfgxy = B(Bf)gxy = (Bf)(gx)y = Bf(gx)y = (f . gx) y abc a bc abc 

We can drop as y at the end (this is called eta-reduction : Gy=Hy β†’ G=H if y does not appear inside H 1 ). But also, another way to present this,

 BBBfgxy = B(Bf)gxy = ((f .) . g) xy = f (gxy) -- (.) f == (f .) -- compare with: (f .) gx = f (gx) 

((f .) . g) xy may be easier to enter than ((.).(.)) fgxy , but YMMV.


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

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

which is nonsense.

+2
source share

All Articles