4

我将集合和映射实现为不平衡的二叉树。因为集合和映射非常相似,我实际上只是从头开始编写映射的实现,然后将集合简单地实现为从键到单元的映射:

signature EQ =
sig
  type t;

  val eq : t * t -> bool;
end;

signature ORD =
sig
  include EQ;

  val lt : t * t -> bool;
end;

signature SET =
sig
  structure Elem : EQ;
  type      set;

  val empty  : set;
  val member : Elem.t * set -> bool;
  val insert : Elem.t * set -> set option;
end;

signature MAP =
sig
  structure Key : EQ;
  type      'a map;

  val empty  : 'a map;
  val lookup : Key.t      * 'a map -> 'a option;
  val insert : Key.t * 'a * 'a map -> 'a map option;
end;

functor UnbalancedMap (Key : ORD) :> MAP =
struct
  structure Key     = Key;
  datatype  'a tree = E | T of Key.t * 'a * 'a tree * 'a tree;
  type      'a map  = 'a tree;

  val empty = E;

  fun lookup (k, t) =
    let
      fun loop (k, E, E) = NONE
        | loop (k, E, T (x, y, _, _)) =
          if Key.eq (k, x) then SOME y
                           else NONE
        | loop (k, t as T (x, _, a, b), r) =
          if Key.lt (k, x) then loop (k, a, r)
                           else loop (k, b, t);
    in
      loop (k, t, E)
    end;

  fun insert (k, v, t) =
    let
      exception Exists;

      fun loop (k, v, E, E) = T (k, v, E, E)
        | loop (k, v, E, T (x, _, _, _)) =
          if Key.eq (k, x) then raise Exists
                           else T (k, v, E, E)
        | loop (k, v, t as T (x, y, a, b), r) =
          if Key.lt (k, x) then T (x, y, loop (k, v, a, r), b)
                           else T (x, y, a, loop (k, v, b, t));
    in
      SOME (loop (k, v, t, E)) handle Exists => NONE
    end;
end;

functor UnbalancedSet (Elem : ORD) :> SET =
struct
  structure Map  = UnbalancedMap (Elem);
  structure Elem = Map.Key;
  type      set  = unit Map.map;

  val empty = Map.empty;

  fun member (x, t) = case Map.lookup (x, t) of
      NONE => false 
    | _    => true;

  fun insert (x, t) = Map.insert (x, (), t);
end;

假设我使用其他数据结构提出了另一种地图实现。然后我应该能够重用该数据结构来将集合定义为从键到单元的映射:

functor AnotherMap (Key : EQ) :> MAP =
struct
  (* ... *)
end;

functor AnotherSet (Elem : EQ) :> SET =
struct
  structure Map  = AnotherMap (Elem);
  structure Elem = Map.Key;
  type      set  = unit Map.map;

  val empty = Map.empty;

  fun member (x, t) = case Map.lookup (x, t) of
      NONE => false 
    | _    => true;

  fun insert (x, t) = Map.insert (x, (), t);
end;

但是,如果我想出任意多个映射的实现,重新定义使用与这些映射相同的数据结构的集合很快就会变得乏味。我真正想要的是一个函子,它将函子从 X 带到 MAP,并产生一个从 X 到 SET 的函子,其中 X 是任何包含 EQ(或可能是 EQ 本身)的签名。这在标准 ML 中可能吗?

4

1 回答 1

5

作为非标准扩展,是的。我相信您正在寻找的功能被 SML/NJ 称为“高阶函子”。以下是有关其实施的一些有限细节。

不过,我强调这不是SML 的标准功能。使用 SML 模块系统无法直接实现这一点。

于 2013-04-29T13:41:11.927 回答