[Haskell-cafe] Re: Exercise in point free-style

Thomas Davie tom.davie at gmail.com
Fri Sep 1 20:48:30 EDT 2006

```Shorter, although perhaps less insightful.

Bob

On 2 Sep 2006, at 01:36, Lennart Augustsson wrote:

> An easy way to solve this is to ask lambdabot.  Log on to the
> lennart: @pl  \ f l -> l ++ map f l
> lambdabot: ap (++) . map
>
> Notice how it's much shorter than the Hughes' solution. :)
>
> 	-- Lennart
>
> On Sep 1, 2006, at 13:11 , John Hughes wrote:
>
>>> 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
>>
>>
>> _______________________________________________