{----------------------------------------------------------------}
{--- Generalised divide-and-conquer ---}
{----------------------------------------------------------------}
list a ::= Nil | Cons a (list a);
tree a ::= Leaf | Branch (tree a) a (tree a) ; ;;
{----------------------------------------------------------------}
map f l = case l of Nil -> Nil; Cons x xs -> Cons (f x) (map f xs) end;
{----------------------------------------------------------------}
{-- unfortunately, abstract interpretation is not powerful
enough to see we never need this. --}
error = error;
{----------------------------------------------------------------}
{-- list subscription --}
{-- This is bound to get us a lousy abstract interpretation,
since it means using different elements of the list
in different ways --}
nth n l = case l of
Nil ->
error;
Cons x xs ->
case n > 0 of False -> x; True -> nth (n-1) xs end
end;
{----------------------------------------------------------------}
{-- divide & conquer --}
{-- allow the merge function to access the original problem
as well as solved subproblems --}
divide_conq is_base base_fn merge_fn split_fn problem
= case is_base problem of
True -> base_fn problem;
False -> merge_fn problem
(map (divide_conq is_base base_fn merge_fn split_fn)
(split_fn problem))
end;
{----------------------------------------------------------------}
{-- pretty straightforward stuff --}
treeSum tree
= let
t_is_base
= \t -> case t of Leaf -> True; Branch l x r -> False end;
t_base_fn
= \t -> 0;
t_split_fn
= \t -> case t of Branch l x r -> Cons l (Cons r Nil);
Leaf -> error end;
t_merge_fn
= \original_tree solved_subproblems
-> case original_tree of
Leaf -> error;
Branch original_l original_x original_r
-> (nth 0 solved_subproblems) +
(nth 1 solved_subproblems) + original_x
end
in
divide_conq t_is_base t_base_fn t_merge_fn t_split_fn tree;
{----------------------------------------------------------------}
mirror tree
= let
m_is_base
= \t -> case t of Leaf -> True; Branch l x r -> False end;
m_base_fn
= \t -> t;
m_split_fn
= \t -> case t of Branch l x r -> Cons l (Cons r Nil);
Leaf -> error end;
m_merge_fn
= \original_tree solved_subproblems
-> case original_tree of
Leaf -> error;
Branch original_l original_x original_r
-> Branch (nth 1 solved_subproblems)
original_x
(nth 0 solved_subproblems)
end
in
divide_conq m_is_base m_base_fn m_merge_fn m_split_fn tree;
{----------------------------------------------------------------}
{--- end divide.cor ---}
{----------------------------------------------------------------}