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:
(f, (x, y))
.assoc1 :: (a, (b, c)) -> ((a, b), c)
to the tuple and get ((f, x), y)
.($)
to the first element of the pair and get (f x, y)
.($)
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
?
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
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