SML 使用带签名的 abstype

SML use abstype with signatures

我正在编写一个库来处理标准 ML 中的简单图像。它应该支持用作每个像素颜色的不同类型,例如布尔值,Word8.word,等等

我有一个abstype 'a image,所有常用函数都定义为独立于表示('a 是颜色表示),但输出格式不同,所以我想要不同的结构.

有没有办法在结构中 "open" 一个 abstype?我只能以一种非常丑陋的方式让它工作:

abstype 'clr absimage = Image of {width : int, height : int, data : 'clr array array}
with
    fun createFunc (w, h) f = Image {width = w, height = h, data = ...}
    fun createBlank (w, h) clr = createFunc (w, h) (fn _ => clr)
    ...
end
signature IMAGE = sig
    type colour
    type image
    val createFunc : (int * int) -> (int * int -> colour) -> image
    val createBlank : (int * int) -> colour -> image
    ...
    val toBinPPM : image -> string -> unit
end
functor ImageFn(C : sig type colour end) = struct
    open C
    type image = colour absimage
    val createFunc = createFunc
    val createBlank = createBlank   
    ...
end
structure Image8 :> IMAGE = struct
    structure T = ImageFn(struct type colour = Word8.word end)
    open T

    fun toBinPPM img filename = ...
end

特别是,函子的定义需要为abstypewith ... end部分定义的所有函数编写类似val name = name的语句。

还是我的做法完全错误?

这种 abstypesignature 的组合是我尝试用 abstype 中的常用方法重新创建 OOP 的抽象 class 并要求在所有结构中实现其他方法使用signature

P.S。为什么 SML 不允许像 open (ImageFn(struct ... end)) 这样的语句并强制使用临时结构(上面代码中的 T)?

没有理由在今天的 SML 中使用 abstype。认为它已弃用。它是前模块时代的遗留物。您可以通过结构、签名和密封(:> 运算符)实现隐藏类型构造函数的相同效果,但方式更加灵活和一致。这也解释了为什么它不能很好地与模块集成——它早于它们并且基本上被它们取代了。

在您的具体示例中,不使用 abstype,而是直接在 ImageFn 函子的主体中将 image 定义为 datatype,并隐藏其构造函数带有签名注释,如下所示:

signature IMAGE =
sig
  type colour
  type image
  val createFunc : int * int -> (int * int -> colour) -> image
  val createBlank : int * int -> colour -> image
  ...
end

signature IMAGE8 =
sig
  include IMAGE
  val toBinPPM : image -> string -> unit
end

functor ImageFn(type colour) :> IMAGE =
struct
  datatype image = Image of {width : int, height : int, data : colour array array}
  fun createFunc (w, h) f = Image {width = w, height = h, data = ...}
  fun createBlank (w, h) clr = createFunc (w, h) (fn _ => clr)
  ...
end

structure Image8 :> IMAGE8 =
struct
  structure T = ImageFn(type colour = Word8.word)
  open T
  fun toBinPPM img filename = ...
end

编辑:事实上,在这种情况下甚至没有必要将 image 定义为数据类型。普通类型也可以,并使代码稍微简单一些:

type image = {width : int, height : int, data : colour array array}

至于你的PS问题:是的,我也不知道。没有特别的理由。一些 SML 方言将其作为扩展来实现。