【问题标题】:SML record subset and updateSML 记录子集和更新
【发布时间】:2014-07-24 16:21:51
【问题描述】:

是否有更直接的方法(并且由于涉及的维护和编辑量而不太容易出错),以实现与以下相同的目的,即:1)在给定名称的情况下获取记录元素的子集感兴趣的成员列表,2) 并使用子集记录的名称从子集记录更新记录?

val r = {a = 1, b = 2, c = 3, d = 4, e = 5}
val s = {b = #b r, c = #c r, d = #d r}
val r = {a = #a r, b = #b s, c = #c s, d = #d s, e = #e r}

我所期望的可能是这样的:

val r = {a = 1, b = 2, c = 3, d = 4, e = 5}
val s = #(b, c, d) r
val r = r / s

正如 Sebastian Paaske Tørhol 所说,可以这样提取记录的一部分:

val {b, c, d, ...} = r

不幸的是,这不会将子集绑定到单个名称,因为作为示例,这不起作用:

val s = {b, c, d, ...} = r

【问题讨论】:

    标签: sml


    【解决方案1】:

    不,没有。曾经有过更广泛的记录操作 (Functional record extension and row capture) 的提议,作为短暂的继任者 ML 工作的一部分。有了这个,你可以写,例如,

    val r = {a = 1, b = 2, c = 3, d = 4, e = 5}
    val {a, e, ... = s} = r
    val t = {a = a+1, e = e-1, ... = s}
    

    不幸的是,没有人在真正的编译器中实现过它。

    【讨论】:

    • 有一些与功能记录类型和子类型相关的东西,名为 SystemF<: : href="https://en.wikipedia.org/wiki/System_F-sub" rel="nofollow" target="_blank">System F‑sub (en.wikipedia.org) 和 Subtyping (en.wikipedia.org)。可能值得调查。
    • 不幸的是,子类型为语言带来了复杂性和问题的全新维度,尤其是在与多态性结合时,例如在 F-sub 和扩展中。几十年来,它一直困扰着 OO 类型系统,而您通常不希望在函数式语言中出现这种情况。一个更好的选择是行多态性,它至少允许实际的类型推断。
    • 困扰 OO 的是缺乏真正的形式化和形式化方法:它并没有停止在它无法正确处理的点上。否则,我同意你的看法,如果这更复杂,安全性也更复杂(但并非不可能,如果我没记错的话,这个逻辑是合理的)。感谢您的评论。
    • 嗯,已经有很多形式化了。但是子类型是一个兔子洞——看例如在 Abadi & Cardelli,或者看看 Scala 的复杂程度。某些版本的 F-omega-sub 已经无法确定。所有这一切都是因为表达能力的增加相当微弱(与参数多态性相比)。
    • 我可能并没有真正理解什么是正式的子类型。
    【解决方案2】:

    您可以使用模式匹配来提取记录的相关部分:

    例子:

    val question = { title = "SML record subset and update",
                     author = "Hibou57",
                     tags = ["SML"] }
    
    val { title = t, tags = ts, ... } = question
    

    这会将标题绑定到t,并将标签绑定到ts

    如果您愿意,也可以简单地省略名称:

    val { title, tags, ... } = question
    

    这会将标题绑定到title,并将标签绑定到tags

    就更新而言,遗憾的是,标准 ML 没有很好的方法来更新记录,而无需明确设置每个字段。

    【讨论】:

    • 我不知道模式匹配可以以这种方式与记录一起使用。感谢您的提示。我会在选择这个答案之前等待,只是等待是否有人高兴地对更新部分有想法。
    • 这个“...”是怎么命名的?我以前从未见过它,而且它似乎是必需的,而不仅仅是您的 sn-p 中的占位符。一个问题是:虽然这会提取记录的一部分,但这不能将此子集绑定到单个名称。
    • 回答我自己:“…”只是以其通用名称命名,即省略号(SML 没有给它任何专用名称)。
    猜你喜欢
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多