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
>