Suppose I have two functions, f:X->Y and g:Y*Y->Z. 
I want to make a third function, h(a, b) = g(f(a), f(b)).
h a b = g (f a) (f b)
Is there any way to write it like h(a, b) = g*f (a, b)?
And what if h(a,b,c,d) = g2*g1*f2*f1 (a,b,c,d), where g_i takes 2 args?
Searching Hoogle for functions with the right signature reveals on from Data.Function. According to its documentation,
g `on` f
seems to be what you want.
The on combinator (in Data.Function, as pointed out by gspr in another answer) is defined by
g `on` f = \x y -> g (f x) (f y)
Which would allow you to write
h = g `on` f
You can make higher-dimensional generalizations of this, for example
g `on3` f = \x y z -> g (f x) (f y) (f z)
g `on4` f = \w x y z -> g (f w) (f x) (f y) (f z)
So that you could write
h = g `on3` f
There may be a way to write on3 and on4 in terms of on, but if there is I can't see it at the moment.
You may also find Arrows interesting. Here's one way to do it:
h g f a b = uncurry g ((f *** f) (a, b))
Which is equivalent to your example (except that g and f are not free) and on.  Using:
definition of *** for functions:
(***) f g ~(x,y) = (f x, g y)
definition of uncurry:
uncurry f p =  f (fst p) (snd p)
And substituting them into the original equation:
h g f a b = uncurry g (f a, f b)  (used *** definition)
h g f a b = g (f a) (f b) (used uncurry definition)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With