elm - 在Elm 0.19中可扩展的记录是没有用的吗?

标签 elm

可扩展记录是Elm最令人惊奇的功能之一,但是自v0.16开始,添加和删除了字段is no longer available。这使我处于尴尬的境地。

考虑一个例子。我想给一个随机的东西t命名,可扩展的记录为我提供了一个完美的工具:

type alias Named t = { t | name: String }

“好吧,”编辑说。现在我需要一个构造函数,即一个具有指定名称的东西的函数:
equip : String -> t -> Named t
equip name thing = { thing | name = name }  -- Oops! Type mismatch

编译失败,因为{ thing | name = ... }语法假定thing是带有name字段的记录,但是类型系统无法保证这一点。实际上,我尝试使用Named t表示相反的内容:t应该是没有自己的name字段的记录类型,并且该函数将此字段添加到记录中。无论如何,要实现equip函数,必须添加字段。

因此,以多态方式编写equip似乎是不可能的,但是这可能没什么大不了的。毕竟,只要有时间我想给一些具体的事情起个名字,我都可以手工完成。更糟糕的是,逆函数extract : Named t -> t(删除命名事物的名称)需要字段移除机制,因此也无法实现:
extract : Named t -> t
extract thing = thing  -- Error: No implicit upcast

这将是非常重要的功能,因为我有很多例程可以接受老式的未命名事物,并且我需要一种将它们用于命名事物的方法。当然,大量重构这些功能是不合格的解决方案。

最后,经过漫长的介绍之后,让我陈述一下我的问题:
  • 现代Elm是否可以替代旧的不赞成使用的字段添加/删除语法?
  • 如果没有,上面是否有一些内置函数,例如equipextract?对于每种自定义可扩展记录类型,我都希望有一个多态分析器(一个提取其基础部分的函数)和一个多态构造函数(一个将基础部分与加法运算相结合并生成记录的函数)。
  • (1)和(2)的否定答案将迫使我以更传统的方式实现Named t:
    type Named t = Named String t
    

    在这种情况下,我无法达到可扩展记录的目的。有没有积极的用例,在这种情况下可扩展记录起着至关重要的作用?
  • 最佳答案

    类型{ t | name : String }表示具有name字段的记录。它不会扩展t类型,而是扩展了编译器有关t本身的知识。

    因此,实际上equip的类型是String -> { t | name : String } -> { t | name : String }

    而且,正如您所注意到的,Elm不再支持向记录中添加字段,因此即使类型系统允许了您想要的内容,您仍然无法做到这一点。 { thing | name = name }语法仅支持更新{ t | name : String }类型的记录。

    同样,不支持从记录中删除字段。

    如果确实需要具有可以添加或删除字段的类型,则可以使用Dict。其他选项是手动编写转换器,或者创建并使用代码生成器(这是一段时间内JSON解码样板的推荐解决方案)。

    关于可扩展记录,Elm不再真正支持“可扩展”部分–唯一剩下的部分是{ t | name : u } -> u投影,因此也许应该将其称为作用域记录。 Elm docs本身承认目前的可扩展性不是很有用。

    关于elm - 在Elm 0.19中可扩展的记录是没有用的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55551328/

    相关文章:

    cookies - 如何在Elm中读取cookie?

    Elm 架构和任务

    elm - 从 http 响应中获取 header

    functional-programming - Elm:理解 foldp 和鼠标点击

    javascript - Elm 中的并发

    elm - 如何将数字转换为字符串

    css - 努力将 CSS 样式应用到 Elm 应用程序

    榆树分割订阅?

    html - 在 Elm 中为样式元素 (v5) 分配 id

    node.js - 尝试在 ubuntu 上使用 sudo 安装 elm 时出现权限被拒绝错误