# Including Code in Multiple Modules

Suppose we wanted to write a function that could add a bunch of elements to a set, something like:

(* [add_all l s] is the set [s] unioned with all the elements of [l] *)
let rec add_all lst set = match lst with
| [] -> set


(Of course, we could code that up more tersely with a fold function.)

One possibility would be to copy that code into both structures. That would compile, but it's poor software engineering. If ever an improvement needs to be made to that code (e.g., replacing it with a fold function), we have to remember to do it in two places. So let's rule that out right away as a non-solution.

So instead, after defining both set implementations above, suppose we try to enter that code into utop outside of either implementation. We'll get an error:

# let rec add_all lst set = match lst with
| [] -> set


The problem is we either need to choose ListSetDups.add or ListSetNoDups.add. If we pick the former, the code will compile, but it will be useful only with that one implementation:

# let rec add_all lst set = match lst with
| [] -> set
- : 'a list -> 'a ListSetNoDups.t -> 'a ListSetNoDups.t = <fun>


We could make the code parametric with respect to the add function:

let rec add_all' add lst set = match lst with
| [] -> set



But this is annoying in a couple ways. First, we have to remember which function name to call, whereas all the other operations that are part of those modules have the same name, regardless of which module they're in. Second, the add_all functions live outside either module, so clients who open one of the modules won't automatically get the ability to name those functions.

Let's try to use includes to solve this problem. First, we write a module that contains the parameterized implementation of add_all':

module AddAll = struct
| [] -> set
end

module ListSetNoDupsExtended : SetExtended = struct
include ListSetNoDups
end

module ListSetDupsExtended : SetExtended = struct
include ListSetDups
end


We've succeeded, partially, in achieving code reuse. The code that implements add_all' has been factored out into a single location and reused in the two structures. So we could now replace it with an improved (?) version using a fold function:

module AddAll = struct

But we've partially failed. We still have to write an implementation of add_all in both modules, and worse yet, those implementations are identical. So there's still code duplication occurring.