Derek Elkins derek.a.elkins at gmail.com
Wed Sep 26 22:30:42 EDT 2007

```On Wed, 2007-09-26 at 18:50 -0400, Steven Fodstad wrote:
> 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 (*))

As a side note, this is essentially how all higher order functions are
handled in category theory (well, in cartesian closed categories.)

```