Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement uncurry point-free in Haskell without app?

I have been wondering how different standard Haskell functions could be implemented point-free. Currently, I am interested in uncurry and I feel this one is quite non-trivial.

The main problem is that we are unable (or as it seems to me) to group the arguments. If we had uncurry (in fact, uncurry ($) would suffice) in use, the solution would have been quite simple:

  1. Make a tuple (f, (x, y)).
  2. Apply assoc1 :: (a, (b, c)) -> ((a, b), c) to the tuple and get ((f, x), y).
  3. Apply the uncurried ($) to the first element of the pair and get (f x, y).
  4. Apply the uncurried ($) to the pair itself and get f x y.

Without the uncurried ($) we would have to extract both elements of the pair separately. E.g.:

uncurry f pair = f (fst pair) (snd pair)

I do not reckon this to be a smooth way to implement something point-free.

In fact, we have got this uncurried ($) at our behest: Control.Arrow.apply (other useful for the solution combinators could also be imported from Control.Arrow). Therefore:

import Control.Arrow ((>>>), (&&&), first, app)

myUncurry = let myAssoc1 = (fst &&& (fst . snd)) &&& (snd . snd)
            in (,) >>> (>>> myAssoc1 >>> first app >>> app) 

Yet, this feels a small bit like cheating.

Are there any other approaches towards this problem which do not require anything like app?

like image 825
Zhiltsoff Igor Avatar asked Dec 13 '22 08:12

Zhiltsoff Igor


1 Answers

join on functions gives you (a -> a -> b) -> a -> b, so:

myUncurry f = join (\x y -> f (fst x) (snd y))
myUncurry f = join (\x -> f (fst x) . snd)
myUncurry f = join ((.snd) . f . fst)
myUncurry f = join ((.fst) ((.snd) . f))
myUncurry f = join ((.fst) ((.) (.snd) f))
myUncurry = join . (.fst) . \f -> (.) (.snd) f
myUncurry = join . (.fst) . ((.snd).)

join . (.fst) . ((.snd).) is very readable indeed

like image 111
Ry- Avatar answered Jan 19 '23 00:01

Ry-