Jonathan Cast jcast at ou.edu
Tue Sep 25 11:42:04 EDT 2007

```On Tue, 2007-09-25 at 11:40 +0100, Andrew Coppin wrote:
> Aaron Denney wrote:
> > On 2007-09-25, Andrew Coppin <andrewcoppin at btinternet.com> wrote:
> >
> >> OK, *now* I'm puzzled... Why does map . map type-check?
> >>
> >
> > (map . map) = (.) map map
> >
> > (.) :: (a -> b) -> (b -> c) -> a -> c
> >     = (a -> b) -> (b -> c) -> (a -> c)
> >
> > The first two arguments of (.) are 1-argument functions.
> >
> > map :: (d -> e) -> [d] -> [e]
> >     =  (d -> e) -> ([d] -> [e])
> >
> > map is either a two argument function _or_ a function that takes one
> > argument (a function) and returns a function.
> >
> > In this latter view, for the first argument, of (.), we need:
> >
> > a = d -> e
> > b = [d] -> [e]
> >
> > And for the second we know
> > b = [d] -> [e]
> > so
> > c = [[d]] -> [[e]]
> >
> > for everything to be consistent.
> >
> > It's much clearer when you think of map not as "running this function
> > over this list", but rather "turning this function that operates on
> > elements into a function that operates on lists".  Doing that twice (by
> > composing) turns a function that operates on elements into a function
> > that operates on lists of lists.
> >
>
> I just found it rather surprising. Every time *I* try to compose with
> functions of more than 1 argument, the type checker complains.
> Specifically, suppose you have
>
>   foo = f3 . f2 . f1
>
> Assuming those are all 1-argument functions, it works great. But if f1
> is a *two* argument function (like map is), the type checker refuses to
> allow it, and I have to rewrite it as
>
>   foo x y = f3 \$ f2 \$ f1 x y
>
> which is really extremely annoying...
>
> I'm just curiose as to why the type checker won't let *me* do it, but it
> will let *you* do it. (Maybe it hates me?)

In f . g, if g takes two arguments, f has to take a function as the
first argument (because that's what g returns).

jcc

```