Wed Sep 26 18:50:35 EDT 2007

Andrew Coppin wrote:
>> 2007/9/25, Andrew Coppin <andrewcoppin at btinternet.com>:
>>
>>> This is why I found it so surprising - and annoying - that you can't
>>> use
>>> a 2-argument function in a point-free expression.
>>>
>>> For example, "zipWith (*)" expects two arguments, and yet
>>>
>>>   sum . zipWith (*)
>>>
>>> fails to type-check. You just instead write
>>>
>>>   \xs ys -> sum \$ zipWith(*) xs ys
>>>
>>>
>>
>> (sum . zipWith (*)) xs ys
>> == (sum (zipWith (*) xs)) ys
>>
>> so you try to apply sum :: [a] -> Int to a function (zipWith (*) xs)
>> :: [a] -> [b], it can't work !
>>
>> (sum.) . zipWith (*)
>> works, but isn't the most pretty expression I have seen.
>>
>
> I'm still puzzled as to why this breaks with my example, but works
> perfectly with other people's examples...
>
> So you're saying that
>
>  (f3 . f2 . f1) x y z ==> f3 (f2 (f1 x) y) z
>
> ? In that case, that would mean that
>
>  (map . map) f xss ==> map (map f) xss
>
> which *just happens* to be what we want. But in the general case where
> you want
>
>  f3 (f2 (f1 x y z))
>
> there's nothing you can do except leave point-free.
Well, there's one thing.  You can change your three argument function
into a one argument function of a 3-tuple, and then change the composed
function back again:

let uncurry3 = \f (x,y,z) -> f x y z
curry3 = \f x y z -> f (x,y,z)
in curry3 \$ f3 . f2 . uncurry3 f1

In your earlier example, this would have been:
curry \$ sum . uncurry (zipWith (*))