Function composition and currying

oleg@pobox.com oleg@pobox.com
Thu, 17 Jul 2003 17:42:32 -0700 (PDT)


What I nice application for a multi-variadic compositional operator
mcomp [1]. Only one operator does the trick, for functions of
arbitrary number of curried arguments. And I really mean the arbitrary
number of arguments, in both functions under composition. Given

> f1 x = x*x
> g2 a b = a + b
> g3 a b c = a + b + c

we can easily compose g2 with f1
*Main> (g2 `mcomp` f1) (1::Int) (2::Int)
9

and g3 with f1 
*Main> (g3 `mcomp` f1) (1::Int) (2::Int) (3::Int)
36

But we can just as easily compose f1 with g2:
*Main> (f1 `mcomp` g2) (2::Int) (3::Int)
7
(that is, square the first number and add the second)

and f1 with g3
*Main> (f1 `mcomp` g3) (2::Int) (3::Int) (4::Int)
11


What's more, we can even compose g2 with g3 or g3 with g2!

*Main> (g3 `mcomp` g2) (1::Int) (2::Int) (3::Int) (4::Int)
10
*Main> (g2 `mcomp` g3) (1::Int) (2::Int) (3::Int) (4::Int)
10

The Web page referenced below shows an advanced application of mcomp, to
point-free programming (categorical products).

[1] http://pobox.com/~oleg/ftp/Haskell/types.html
The following code, excerpted from [1], was used for the above
examples. -fglasgow-exts are needed.

> class MCompose f2 cp gresult result | f2 cp gresult -> result, f2->cp
>   where
>     mcomp:: (f1->f2) -> (cp->gresult) -> (f1 -> result)
>   
> -- Class instances. Please keep in mind that cp must be a non-functional type
> -- and f2 and cp must be the same. These instances enumerate the base cases.
> 
> instance MCompose (Maybe b) (Maybe b) c c where
> --mcomp f::(a->(Maybe b)) g::((Maybe b)->c) :: a->c
>     mcomp f g = g . f
> 
> instance MCompose [b] [b] c c where
> --mcomp f::(a->[b]) g::([b]->c) :: a->c
>     mcomp f g = g . f
>   
> instance MCompose Int Int c c where
> --mcomp f::(a->Int) g::(Int->c) :: a->c
>     mcomp f g = g . f
> 
> instance MCompose Char Char c c where
> --mcomp f::(a->Char) g::(Char->c) :: a->c
>     mcomp f g = g . f
> 
> instance MCompose (a,b) (a,b) c c where
>     mcomp f g  =  g . f
> 
> -- Induction case
> instance (MCompose f2 cp gresult result) => 
> 	MCompose (f1->f2) cp gresult (f1->result) where
>     mcomp f g = \a -> mcomp (f a) g
>