Optimal matrix chain multiplication
```> module MatrixMult where

> import Array
> import List
```
The signature:
```> data Matrixchain = Mult   Matrixchain Matrixchain |
>                    Single (Int, Int)
>                                       deriving (Show, Eq, Ord)
```
The yield grammar:
```> matrixmult alg f = axiom matrices where

>   (single, mult, h) = alg

>   matrices = tabulated (
>              single <<< achar                  |||
>              mult   <<< matrices +~+ matrices  ... h)
```
Bind input:
```>   z         = mk f
>   (_,n)     = bounds z
>   axiom     = axiom' n
>   tabulated = table n
>   achar     = achar' z
```
Enumeration algebra:
```> enum :: Matrixmult_Algebra (Int, Int) Matrixchain
> enum  = (single, mult, h) where
>   single = Single
>   mult   = Mult
>   h      = id
```
Pretty printing algebra:
```> prettyprint :: Matrixmult_Algebra (Int, Int) String
> prettyprint = (single, mult, h) where
>   single (a,b) = "|" ++ show a ++ "x" ++ show b ++ "|"
>   mult x y     = "(" ++ x ++ "*" ++ y ++ ")"
>   h            = id
```
Counting algebra:
```> count :: Matrixmult_Algebra (Int, Int) Int
> count = (single, mult, h) where
>   single (r,c) = 1
>   mult x y     = x*y
>   h []         = []
>   h xs         = [sum xs]
```
Scoring algebra:
```> minmult :: Matrixmult_Algebra (Int, Int) (Int, Int, Int)
> minmult = (single, mult, h) where
>   single (r,c)                = (r, 0 ,c)
>   mult (r, m, c) (r', m', c') = (r, m+m'+ r*c*c', c')
>   h []                        = []
>   h xs                        = [minimum xs]
```
Problem variation:
Minimizing intermediate storage:
```> minmem :: Matrixmult_Algebra (Int, Int) (Int, Int, Int)
> minmem = (single, mult, h) where
>   single (r,c)              = (r,0,c)
>   mult (r,m,c) (r',m',c')   = (r, minimum
>                                 [maximum [m,r*c+ m',r*c
>                                   + r'* c' + r*c'],
>                                  maximum [m',r'*c'+ m,r*c
>                                   + r'* c' + r*c']],c')
>   h []                      = []
>   h l                       = [minimum(l)]
```
Algebra type:
```> type Matrixmult_Algebra alphabet answer = (
>   alphabet -> answer,         -- single
>   )
```
Algebra cross product:
```> infix ***
> (***) :: Eq answer1 =>