【问题标题】:SML Polymorphic references in signatures签名中的 SML 多态引用
【发布时间】:2017-10-25 11:21:09
【问题描述】:

有没有办法在签名中制作多态引用常量?

这段代码可以编译,但不是我需要的:

signature NAME = sig
    type 'a name
    val empty : 'a name
end

structure Name :> NAME  = struct
    datatype 'a name = Nil | Val of 'a
    val empty = Nil
end

添加所需的引用:

signature NAME = sig
    type 'a name
    val empty : 'a name ref
end

structure Name :> NAME  = struct
    datatype 'a name = Nil | Val of 'a
    val empty = ref Nil
end

产生以下错误:

error: Structure does not match signature.
    Signature: val empty: 'a name ref
    Structure: val empty: 'a name ref
    Reason: Can't match 'a to 'a (Type variable is free in surrounding scope)
Found near struct datatype 'a name = Nil | Val of 'a  val empty = ref Nil end

【问题讨论】:

    标签: reference functional-programming polymorphism sml


    【解决方案1】:

    这实际上与签名无关;如果你写(在顶层),你会遇到同样的问题:

    val emptyListRef = ref nil
    val emptyIntList = (! emptyListRef) : int list
    val emptyStringList = (! emptyListRef) : string list
    

    问题是emptyListRef——或者在你的情况下empty——不能是多态的。 (您的编译器声称empty 具有'a name ref 类型,但它真正 的意思是empty 将具有某种类型的?? name ref,它还没有弄清楚?? 会是什么。)

    当您考虑到如果empty 多态时,此限制是有意义的,那么您将能够编写如下内容:

    val () = empty := Val 3
    val Val (x : string) = !empty
    

    您将empty 设置为保存int Name,然后像保存string Name 一样读取它。无法说服编译器相信您不会这样做。

    一般规则是,只有当右侧采用几种简单形式之一时,值绑定才允许是多态的,例如构造函数(ref! 除外)和常量和 fn-表达式的组合,已知是安全的(因为它们不能启用上述不当行为)。这条规则称为value restriction;您可以谷歌该词以获取更多信息。

    【讨论】:

    • 谢谢!我很困惑,因为datatype 'a name = Nil | Val of 'a val h = ref Nil val _ = h := Val 5 不会产生错误,但这会:datatype 'a name = Nil | Val of 'a val h = ref Nil; val _ = h := Val 5(注意分号)
    • @zlotnleo:不客气!至于为什么分号会有所不同——标准 ML 的定义并没有真正说明编译器应该如何处理像empty = ref Nil 这样的不可泛化绑定的声明。您的编译器似乎让绑定有点“挂起”,等待获取更多信息,以便推断empty 的类型。一旦它到达分号(结束顶级声明),您的编译器显然会放弃它(返回错误,或分配默认或虚拟类型,或其他东西)。
    猜你喜欢
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    • 2011-07-14
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多