Types 如何从标准ML中的函子参数重新导出数据类型

Types 如何从标准ML中的函子参数重新导出数据类型,types,module,sml,functor,Types,Module,Sml,Functor,在标准ML中,是否可以重新导出作为函子参数接收的结构的一部分的数据类型的构造函数。一些代码可能会使这更容易理解: signature FLAG = sig type t end signature MEMBER = sig structure Flag : FLAG end functor Member(F : FLAG) : MEMBER = struct structure Flag = F end structure M = Mem

在标准ML中,是否可以重新导出作为函子参数接收的结构的一部分的数据类型的构造函数。一些代码可能会使这更容易理解:

signature FLAG =
  sig
    type t
  end

signature MEMBER =
  sig
    structure Flag : FLAG
  end

functor Member(F : FLAG) : MEMBER =
  struct
    structure Flag = F
  end

structure M =
  Member(struct
    datatype t =
      FLAG_1
    | FLAG_2
  end)

val flag1 = M.Flag.FLAG_1;
(* Error: unbound variable or constructor: FLAG_1 in path M.Flag.FLAG_1 *)

上面的例子可能没有任何实际意义,但它只是我在我的一个项目中遇到的问题的一个淡化版本。

如果我正确理解这种情况,
标志
签名中未经劳动的类型规范意味着
t
是不透明的,因此,对于实现
标志
的结构之外的任何东西都是不可访问的

一般来说,在SML中,如果签名指定了模块的接口,那么该模块中唯一可以从外部访问的部分就是签名中明确描述的部分。正如您可能知道的,如果您为某个模块指定了一个接口,那么只有您在签名中明确声明的那些函数和值才可供使用;所有省略的内容都将密封在模块内。同样的原则也适用于未解释的t型规范:由于签名没有说明该类型是如何构成的,因此没有可用的信息

因此,您可以轻松地将值构造函数从作为参数给定的模块重新导出到函子,前提是您已将这些构造函数包含在该模块接口的规范中。例如:

signature FLAG =
sig
    datatype t = FLAG_1 | FLAG_2
end

signature MEMBER =
sig
    structure Flag : FLAG
end

functor Member(F : FLAG) : MEMBER =
struct
    structure Flag = F
end

structure M =
Member(struct
        datatype t =
                 FLAG_1
               | FLAG_2
        end)
然后

- val a = M.Flag.FLAG_1;
val a = FLAG_1 : ?.t
[opening ~/Programming/sml/scratch/scratch.sml]
signature FLAG = sig type t end
structure F : FLAG
val it = () : unit
- F.FLAG_1;
stdIn:63.1-63.9 Error: unbound variable or constructor: FLAG_1 in path F.FLAG_1
这里需要注意的最重要的一点可能是:在实现
标志的模块中,值构造函数的不可访问性与接口的指定方式有关,而与它作为
函子成员的参数出现在这里这一事实无关。我们得到了您在以下程序中使用函子时观察到的相同行为:

signature FLAG =
sig
    type t
end

structure F : FLAG =
struct
    datatype t =
             FLAG_1
           | FLAG_2
end
然后

- val a = M.Flag.FLAG_1;
val a = FLAG_1 : ?.t
[opening ~/Programming/sml/scratch/scratch.sml]
signature FLAG = sig type t end
structure F : FLAG
val it = () : unit
- F.FLAG_1;
stdIn:63.1-63.9 Error: unbound variable or constructor: FLAG_1 in path F.FLAG_1

谢谢你完全正确。我被我的项目迷住了,错过了这样一个事实:每当签名中未指定类型时,就会发生这种情况。在我的特殊情况下,我有两个不同的
标志
结构,有两个不同的
数据类型
声明,因此我不能真正定义签名。再次感谢。我认为(希望!)你的案例应该能够实现!可能正确使用
where
?SML模块系统是我接触过的最激动人心的PL结构之一,但在很多方面,我经常感到局限,遇到障碍,清楚地表明模块系统不是我想要的。我仍在试图找出哪些部分是语言实现强加的限制,哪些部分是良好格式和逻辑正确性的硬限制。我能够通过使用一种称为mixin模式的模式来解决这个问题,在这种模式中,我只需打开
functor
调用的结果。啊,是的!我怀疑它可能以某种方式涉及到
open
,但我不太清楚是怎么回事,因为我一直在考虑打开函子中的模块。