[Haskell-cafe] Re: Exercise in point free-style
John Hughes
rjmh at cs.chalmers.se
Fri Sep 1 13:11:06 EDT 2006
> From: Julien Oster <haskell at lists.julien-oster.de>
> 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
More information about the Haskell-Cafe
mailing list