【问题标题】:How to re-export datatype from functor argument in Standard ML如何从标准 ML 中的函子参数重新导出数据类型
【发布时间】:2017-02-08 04:44:52
【问题描述】:

在标准 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 *)

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

【问题讨论】:

    标签: types module sml functor


    【解决方案1】:

    如果我正确理解这种情况,FLAG 签名中未详细说明的类型规范意味着t 是不透明的,因此对于实现FLAG 的结构之外的任何东西都无法访问。

    一般来说,在 SML 中,如果一个签名为一个模块指定了一个接口,那么该模块中唯一可以从外部访问的部分就是那些在签名中明确描述的部分。您可能知道,如果您为某个模块指定接口,那么只有您在签名中明确声明的那些函数和值才会被提供使用;所有被省略的都被密封在模块内部。同样的原理在这里与 type 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
    

    这里要注意的最重要的一点可能是:实现FLAG的模块中的值构造函数的不可访问性与指定接口的方式有关,与它出现的事实无关这里作为functor Member 的参数。当您在以下程序中使用函子时,我们得到了与您观察到的相同的行为:

    signature FLAG =
    sig
        type t
    end
    
    structure F : FLAG =
    struct
        datatype t =
                 FLAG_1
               | FLAG_2
    end
    

    然后

    [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
    

    【讨论】:

    • 谢谢。你完全正确。我被我的项目冲昏了头脑,错过了一个事实,即只要在签名中未指定类型,就会发生这种情况。在我的特殊情况下,我有两个不同的 FLAG 结构,有两个不同的 datatype 声明,所以我不能真正定义签名。再次感谢。
    • 我认为(希望!)你的案子应该可以实现!也许正确使用where? SML 模块系统是我接触过的最令人兴奋的 PL 结构之一,但我经常在很多方面感到局限性和遇到障碍,这表明模块系统并不是我想要的那样。我仍在试图弄清楚哪些部分是语言实现所施加的限制,哪些部分是格式良好和逻辑正确性的硬限制。
    • 我可以通过使用我称之为 mixin 模式的模式来解决这个问题,我只是将open 称为functor 调用的结果。 gist.github.com/igstan/c566eecc38784216f1499bfe8d91f4c4
    • 啊,是的!我怀疑它可能以某种方式涉及open,但我不太能想到如何,因为我一直在考虑在函子内部打开模块。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    • 2018-08-16
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 2015-09-19
    相关资源
    最近更新 更多