14.6 Functor support
SML# can separately compile functor into an object file, and can be used from other compilation unit through _require declaration. To provide a functor, write the following in its interface file.
functor () =
struct
(* the same as Provide declarations of structure *)
end
is a Standard ML signature. Below is an example of an interface file for binary search tree.
_require "basis.smi"
functor BalancedBinaryTree
(A:sig
type key
val comp : key * key -> order
end
) =
struct
type ’a binaryTree (= boxed)
val empty : ’a binaryTree
val isEmpty : ’a binaryTree -> bool
val singleton : key * ’a -> ’a binaryTree
val insert : ’a binaryTree * A.key * ’a -> ’a binaryTree
val delete : ’a binaryTree * key -> ’a binaryTree
val find : ’a binaryTree * A.key -> ’a option
end
In using functors in separate compilation, one should note the following.
-
•
Functor is not a mechanism for separate compilation. In some existing practice of ML, probably due to the lack of separate compilation, functors can be used to compile some modules independently from the others. For example, if one write
A.sml file: structure A =
struct
...
end B.sml file: structure B =
struct
open A
...
endthen B.sml file directly depends on A.sml file. If one rewrite B.sml using a functor as below then this dependency can be avoided.
B.sml file: functor B(A:sig ... end) =
struct
open A
...
endThis is exactly what separate compilation achieves. A system such as SML# where a complete separate compilation is supported, this form of functor usage is unnecessary and undesirable.
-
•
Usage of functor incurs some overhead. Functors can take types as parameters and therefore strictly more powerful than polymorphic functions. However, this type parameterization requires the compiler to generate code that behaves differently depending on the argument types. The resulting code inevitably incurs more overhead than the corresponding code with the type argument predetermined (i.e. ordinary structures). The programmer who use functor should be aware of this const and restrict functors in cases where the advanced feature of explicit type parameterization is really required.
In the current version of SML# has the following limitation on the usage of functors.
-
•
If a functor has a formal abstract type constructor with type arguments, only heap-allocated internal representations (such as array, boxed, {}, ->, and *) can be applied to the formal type constructor. The following example causes a compile error in SML#.
# functor F(type ’a t) = struct end structure X = F(type ’a t = int);
(interactive):2.17-2.34 Error:
(name evaluation "440") Functor parameter restriction: t