【问题标题】:Can a Standard ML functor take another functor as parameter?标准 ML 仿函数可以将另一个仿函数作为参数吗?
【发布时间】:2013-04-23 02:53:55
【问题描述】:

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

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

【问题讨论】:

    标签: sml functor ml


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-07
      • 1970-01-01
      • 1970-01-01
      • 2010-12-22
      相关资源
      最近更新 更多