标准ML仿函数可以将另一个仿函数作为参数吗?

时间:2013-04-29 12:30:44

标签: sml functor ml

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

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中是否可行?

1 个答案:

答案 0 :(得分:5)

作为非标准扩展,是的。我相信您正在寻找的功能被SML / NJ称为“高阶仿函数”。这是实施的有限detail

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