13

Sometimes I have two functions of the form:

f :: a -> (b1,b2)
h :: b1 -> b2 -> c

and I need the composition g. I solve this by changing h to h':

h' :: (b1,b2) -> c

Can you please show me (if possible) a function m, so that:

(h . m . f) == (h' . f)

Or another way to deal with such situations. Thanks.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
Jogusa
  • 5,530
  • 5
  • 24
  • 23
  • Is there a function (b1,b2) -> b1 -> b2? – Marcin Jun 04 '11 at 14:34
  • 3
    Stop...Hoogle time! [(a -> b -> c) -> ((a,b) -> c)](http://haskell.org/hoogle/?hoogle=%28a+-%3E+b+-%3E+c%29+-%3E+%28%28a%2Cb%29+-%3E+c%29) (transform curried function with 2 arguments into a function that takes a tuple) – Dan Burton Jun 05 '11 at 04:53
  • @DanBurton Or alternatively, [`(strange -> indian -> food) -> ((strange, indian) -> food)`](https://www.haskell.org/hoogle/?hoogle=%28strange+-%3E+indian+-%3E+food%29+-%3E+%28%28strange%2C+indian%29+-%3E+food%29). – Mateen Ulhaq Apr 28 '18 at 07:14

2 Answers2

16

What you're looking to do is to take a function that operates on curried arguments, h, and apply it to the result of f, which is a tuple. This process, turning a function of two arguments into a function that takes one argument that is a tuple, is called uncurrying. We have, from Data.Tuple:

curry :: ((a, b) -> c) -> a -> b -> c 
   -- curry converts an uncurried function to a curried function.

uncurry :: (a -> b -> c) -> (a, b) -> c
   -- uncurry converts a curried function to a function on pairs.

So now we can write:

f :: a -> (b,c)
f = undefined

h :: b -> c -> d
h = undefined

k :: a -> d
k = uncurry h . f

Another tricky way to think of this is via an applicative functor,

k = (h <$> fst <*> snd) . f

Idea from Conor McBride, who'd write it as: (|f fst snd|) . f I think.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
9

What you want to do is uncurry h. This function takes a -> b -> c and converts it into (a, b) -> c.

uncurry h . f
Edward Z. Yang
  • 26,325
  • 16
  • 80
  • 110