
From: Julien Oster
Subject: [Haskell-cafe] Exercise in point free-style I was just doing Exercise 7.1 of Hal Daumé's very good "Yet Another Haskell Tutorial". It consists of 5 short functions which are to be converted into point-free style (if possible).
It's insightful and after some thinking I've been able to come up with solutions that make me understand things better.
But I'm having problems with one of the functions:
func3 f l = l ++ map f l
Looks pretty clear and simple. However, I can't come up with a solution. Is it even possible to remove one of the variables, f or l? If so, how?
Thanks, Julien
Oh, YES!! Two ways to remove l: func3a f = uncurry ((.map f).(++)) . pair func3b f = uncurry (flip (++).map f) . pair And just to make sure they're right: propab new f l = func3 f l == new f l where types = f :: Int->Int quickCheck (propab func3a) quickCheck (propab func3b) If you don't mind swapping the arguments, then propc f l = func3 f l == func3c l f where types = f :: Int->Int func3c l = (l++) . (`map` l) With the arguments swapped, you can even remove both! propd f l = func3 f l == func3d l f where types = f :: Int -> Int func3d = uncurry ((.(flip map)) . (.) . (++)) . pair MUCH clearer! The trick is to observe that l is duplicated, so you need to use a combinator that duplicates something. The only one available here is pair, which you then have to combine with uncurry. It would be nicer to have (f &&& g) x = (f x,g x) available. (&&& is one of the arrow combinators). Then you could remove l by func3e f = uncurry (++) . (id &&& map f) which is sort of readable, and remove both by func3f = (uncurry (++).) . (id &&&) . map John