【问题标题】:SML Common type for different structuresSML 不同结构的通用类型
【发布时间】:2017-12-08 01:44:37
【问题描述】:

我正在标准 ML 中实现集合。目前它看起来像这样:

signature SET = sig
    type t
    type 'a set
    ...
    val map : ('a -> t) -> 'a set -> t set
end

functor ListSetFn (EQ : sig type t val equal : t * t -> bool end)
        :> SET where type t = EQ.t = struct
    type t = EQ.t
    type 'a set = 'a list
    ...
    fun map f = fromList o (List.map f)
end

我希望map 函数能够获取结构SET 中的任何集合,理想情况下甚至不限于来自ListSetFn 函子的集合。但是,在顶层,它只能对由单个结构创建的集合进行操作:调用它的集合,例如:

functor EqListSetFn(eqtype t) :> SET where type t = t = struct
    structure T = ListSetFn(struct type t = t val equal = op= end)
    open T
end

structure IntSet = EqListSetFn(type t = int)
IntSet.map : ('a -> IntSet.t) -> 'a IntSet.set -> IntSet.t IntSet.set

虽然我真的很喜欢它

IntSet.map : ('a -> IntSet.t) -> 'a ArbitrarySet.set -> IntSet.t IntSet.set

有办法吗?我知道它可以在顶层声明,但我想隐藏内部实现,因此使用不透明的签名

【问题讨论】:

    标签: functional-programming sml functor signature ml


    【解决方案1】:

    原则上,有两种方法可以执行这样的参数化:

    1. 将函数包装到自己的函子中,该函子将另一个结构作为参数。

    2. 使函数具有多态性,将相关函数作为单独的参数或作为参数的记录传递给其他类型。

    假设SET 签名包含这些函数:

    val empty : 'a set
    val isEmpty : 'a set -> bool
    val add : 'a * 'a set -> 'a set
    val remove : 'a * 'a set -> 'a set
    val pick : 'a set -> 'a
    

    那么前一个解决方案将如下所示:

    functor SetMap (structure S1 : SET; structure S2 : SET) =
    struct
      fun map f s =
        if S1.isEmpty s then S2.empty else
        let val x = S1.pick s
        in S2.add (f x, map f (S2.remove (x, s)))
        end
    end
    

    对于解决方案 2,您需要直接传递所有相关函数,例如作为记录:

    fun map {isEmpty, pick, remove} {empty, add} f s =
        let
          fun iter s =
            if isEmpty s then empty else
            let val x = pick s
            in add (f x, iter (remove (x, s)))
            end
        in iter s end
    

    FWIW,使用一流的结构会更好,但 SML 没有将它们作为标准功能。

    fun map (pack S1 : SET) (pack S2 : SET) f s =
        let
          fun iter s =
            if S1.isEmpty s then S2.empty else
            let val x = S1.pick s
            in S2.add (f x, iter (S2.remove (x, s)))
            end
        in iter s end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-08
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 2020-05-20
      相关资源
      最近更新 更多