Elixir / Erlang Dialyzer:为什么行为回调的参数类型应该是子类型而不是超类型?

2024-04-05

我有一个行为 X 和一个参数类型的回调函数:

%{a: any}

模块 Y 实现行为 X,实现模块 Y 中的回调函数具有参数类型:

%{a: any, b: any}

Dialyzer 不喜欢这样并抱怨:

(#{'a':=_, 'b':=_, _=>_}) 
is not a supertype of 
#{'a':=_}

这意味着透析器尝试确定实现模块 Y 中的回调参数类型是否是行为 X 中的参数类型的超类型。换句话说,它会询问:

行为X的回调参数类型是%{a: any}的一个子类型 实现模块 Y 的参数类型%{a: any, b: any}?

为什么透析器期望行为回调的参数类型是子类型而不是超类型?

在编程语言类型理论的背景下,子类型已定义 http://www.cs.pomona.edu/~kim/FOOPL/chap5.pdf as:

类型 S 是类型 T 的子类型,写作 S <: t s>

根据上面的定义,如果行为回调的参数类型是,这对我来说是有意义的T实现模块是S。因为实现模块仍然保持行为契约。然而,我不知道为什么透析器期望相反的方式。

请帮助我理解这一点。

注意:这个问题是后续问题,但独立于另一个 SO 问题Erlang (Elixir) Dialyzer - 令人困惑的超类型错误 https://stackoverflow.com/questions/46246998/erlang-elixir-dialyzer-confusing-supertype-error.


透析器是正确的。如果有一种行为X带有类型的回调%{a: any},用户应该能够调用任何声称实现此行为的模块的函数,例如%{a: 1}。你的模块的功能需要%{a: any, b: any}这是一个subtype of %{a: any},这意味着该函数不能被调用%{a: 1}不再符合行为。

另一方面,如果行为的回调具有类型%{a: any, b: any}并且您的模块的函数具有类型%{a: any},那本来就很好,因为%{a: any}是一个超类型%{a: any, b: any}你的模块可以用%{a: 1, b: 2}-- 它可以忽略额外的字段。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Elixir / Erlang Dialyzer:为什么行为回调的参数类型应该是子类型而不是超类型? 的相关文章

  • 当作为函数参数传递时,elixir 是否会生成映射的副本?

    换句话说 我想知道在 Elixir 中 映射是通过值还是通过引用传递给函数 鉴于 Elixir 的无副作用原则 我怀疑这是有价值的 但是大地图不会造成巨大的重复效率低下吗 在此先感谢您的帮助 由于 Elixir 中的所有术语都是不可变的 因
  • 对列表中的 Erlang 记录进行排序?

    我在erlang中有一条记录 record myrec id 0 price 0 quantity 0 然后 我有一个记录列表 我想按 id 和价格按降序和升序排序 其中价格是第一个键 如果两个记录具有相同的价格 我想按 id 对它们进行排
  • Erlang TCP 套接字关闭

    为了学习 Erlang 我正在尝试实现一个基于gen tcp 不幸的是 我的代码似乎触发了一些有线行为 为了演示这个问题 我附上了我的实现的最小化版本 它足以重现该问题 无论 HTTP 请求是什么 它都只是传递静态 200 OK 当我尝试运
  • 为什么使用erts_debug:size/1时atom的内存为零?

    I use erts debug size 1计算erlang VM中atom的内存 但我发现输出为零 谁能解释一下原因 7 gt erts debug size true 0 原因是原子与原子的数据一起保存在原子表中 因此整个节点中只有一
  • 打造 ecto 独一无二的领域

    如何制作一个字段unique在体外 我以为它和Ruby中的活动记录一样 但似乎不是 你想使用唯一约束 3 http hexdocs pm ecto Ecto Changeset html unique constraint 3 这与 Act
  • 可以用宏获取评论吗?

    我试图解析一些代码并重新格式化它们 但似乎引用只会忽略注释 有什么办法可以实现这一点吗 我想我必须深入 erlang 方面 不 您无法在宏内获取代码注释 它们永远不会成为 AST 的一部分 并且仍然被丢弃在 Elixir 的标记器中
  • 我们如何有效地处理 mnesia 记录的时间相关约束?

    我正在将记录写入mnesia 该记录应该保存在那里 仅在允许的时间 24 小时 内 24小时后 在用户修改其中的一部分之前 系统应该自动删除它们 例如 用户获得免费通话时间 用于语音通话 他们应该在给定时间内使用它们 如果他们不使用它 24
  • 您应该将应用程序属性放在 rebar erlang 应用程序中的什么位置?

    新手问题 我编写了第一个基于 rebar 的 erlang 应用程序 我想配置一些基本属性 例如服务器主机等 放置它们的最佳位置在哪里以及如何将它们加载到应用程序中 接下来的步骤是发布版本并在其中创建节点 节点在独立的 Erlang VM
  • Ecto - 验证关联模型的存在

    如何验证 Ecto 中是否存在关联模型 schema foo do has many bar Bar timestamps end required fields w bar invalid 有办法这样做吗 并验证这些字段的最小 最大数量
  • Elixir 中的递归和匿名函数

    我正在尝试定义一个匿名函数来执行点积 我可以将其编码为私有函数 没有任何问题 但我正在努力解决匿名函数语法 我知道我可以以不同的方式实现这一点 但我试图了解如何使用模式匹配和递归来定义匿名函数 这是我当前的实现 dot fn i input
  • GenServer 正常关闭

    我使用 GenServer 编写了一个 Elixir 应用程序 该应用程序在启动时启动外部应用程序 然后将其关闭 并在退出时进行其他清理 我在中添加了启动功能init 1 https hexdocs pm elixir GenServer
  • 检查 Erlang 中的活动计时器

    有没有一种简单的方法来获取所有当前等待的计时器的列表erlang send after erlang apply after等在Erlang中 出于调试目的 您可以使用dbg 首先创建一个 ets 表来存储所有计时器引用 1 gt ets
  • 在 Erlang 中展平嵌套列表的列表

    我正在做练习Erlang编程 问题是 编写一个函数 给定一个嵌套列表的列表 该函数将返回一个平面列表 例子 flatten 1 2 3 4 5 6 1 2 3 4 5 6 提示 使用concatenate解决flatten 这是我的conc
  • 为什么 x = x +1 在 Elixir 中有效?

    我读到的有关 Elixir 的所有内容都表明 赋值应该被视为模式匹配 如果是这样 为什么 x x 1 在 Elixir 中有效 不存在 x x 1 的 x 值 我读到的有关 Elixir 的所有内容都表明 赋值应该被视为模式匹配 在长生不老
  • 将 erlang shell 作为守护进程/服务运行

    显然 我有一个在 Erlang shell 中运行的 Erlang 程序 我想监视它 这就是我要的 当机器启动时 Erlang shell 应该随之启动 并且在 shell 中运行的程序也应该随之启动 如果 Erlang shell 由于某
  • Phoenix 中的 web/static 和 priv/static 有什么区别?

    我对长生不老药和凤凰是新手 现在我在凤凰城的静态资产方面遇到了麻烦 我想在我的页面中添加一个js文件 我在我的模板中添加以下代码 js test js gt gt 然后创建一个js文件web static js test js 但是 我收到
  • 如何将列表转换为元组列表?

    我想转换 z z a z z a a z to z 2 a 1 z 2 a 2 z 1 我该怎么做 所以 我需要累积以前的值 它的计数器和元组列表 我已创建记录 record acc previous counter tuples 重新定义
  • 使用 Ansible 将二进制文件添加到 PATH

    我正在尝试安装Kiex https github com taylor kiex版本管理器Elixir http elixir lang org install html使用 Ansible 的编程语言 这些是我为此使用的戏剧 name K
  • 如何在 Erlang 中将数字转换为单词?

    我发现了一个关于将数字转换为 单词 的有趣问题 代码高尔夫 数字到单词 https stackoverflow com questions 309884 code golf number to words 我真的很想看看你如何在 Erlan
  • Erlang 中的变量

    我有一个非常简单的 Erlang 程序 module test export start 0 Code Z00887 start gt io fwrite Code 我有以下两个错误 c erl6 1 dev test erl 4 之前的语

随机推荐