Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

chaining multi-parameter functions

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?

like image 853
crimsonlander Avatar asked Feb 18 '13 18:02

crimsonlander


3 Answers

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.

like image 168
gspr Avatar answered Sep 22 '22 11:09

gspr


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.

like image 33
Chris Taylor Avatar answered Sep 24 '22 11:09

Chris Taylor


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:

  1. h g f a b = uncurry g (f a, f b) (used *** definition)

  2. h g f a b = g (f a) (f b) (used uncurry definition)

like image 26
Matt Fenwick Avatar answered Sep 20 '22 11:09

Matt Fenwick