Dialyzer 无法识别使用多态类型的函数中的错误

2024-04-22

背景

我正在尝试使用透析器进行多态打字。作为一个例子,我正在使用著名的Option类型(又名 Maybe Monad)现在在许多其他语言中都很流行。

defmodule Test do
  @type option(t) :: some(t) | nothing
  @type some(t) :: [{:some, t}]
  @type nothing :: []

  @spec validate_name(String.t()) :: option(String.t())
  def validate_name(name) do
    if String.length(name) > 0 do
      [{:some, name}]
    else
      nil
    end
  end
end

正如你所看到的,该函数validate_name应该返回(根据规范定义)[{:some, String.t}] | [].

这里的问题是,实际上,该函数正在返回[{:some, String.t}] | nil. nil与空列表不同[].

Problem

鉴于这个问题,我预计透析器会抱怨。然而它很乐意接受这个错误的规范:

$ mix dialyzer
Compiling 1 file (.ex)
Finding suitable PLTs
Checking PLT...
[:compiler, :currying, :elixir, :gradient, :gradualizer, :kernel, :logger, :stdlib, :syntax_tools]
PLT is up to date!
No :ignore_warnings opt specified in mix.exs and default does not exist.

Starting Dialyzer
[
  check_plt: false,
  init_plt: '/home/user/Workplace/fl4m3/grokking_fp/_build/dev/dialyxir_erlang-24.2.1_elixir-1.13.2_deps-dev.plt',
  files: ['/home/user/Workplace/fl4m3/grokking_fp/_build/dev/lib/grokking_fp/ebin/Elixir.Book.beam',
   '/home/user/Workplace/fl4m3/grokking_fp/_build/dev/lib/grokking_fp/ebin/Elixir.DealingWithListsOfLists.beam',
   '/home/user/Workplace/fl4m3/grokking_fp/_build/dev/lib/grokking_fp/ebin/Elixir.Event.beam',
   '/home/user/Workplace/fl4m3/grokking_fp/_build/dev/lib/grokking_fp/ebin/Elixir.FlatMapsVSForComprehensions.beam',
   '/home/user/Workplace/fl4m3/grokking_fp/_build/dev/lib/grokking_fp/ebin/Elixir.ImmutableValues.beam',
   ...],
  warnings: [:unknown]
]
Total errors: 0, Skipped: 0, Unnecessary Skips: 0
done in 0m1.09s
done (passed successfully)

此外,无论我在其中放入什么else分支,结果始终是“快乐的透析器”。

Question

在这一点上,我能想到的唯一合乎逻辑的解决方案是透析器是only关心幸福之路。意思是,它会忽略我的else branch.

如果 dialzyer 只关心快乐路径,那么这可以解释这个问题(毕竟它被称为成功输入),但这也意味着它会完全错过我的代码中的一堆错误。

  • 我对透析器的假设正确吗?
  • 有没有办法让它更精确地发现错误,或者这是透析器使用的算法的限制? (因此无法修复)

也意味着它会完全错过我的代码中的一堆错误。

您的理解是正确的,dialyzer 不是静态类型系统,它只能检测到导致确认类型冲突的错误子集。这详细文章 https://learnyousomeerlang.com/dialyzer解释透析器背后的设计和权衡。

但有一些警告标志,例如underspecs / overspecs / specdiffs,可以检测更多类别的错误:可以找到列表here https://www.erlang.org/doc/man/dialyzer.htmlDialyxir 支持它们命令行选项 https://hexdocs.pm/dialyxir/readme.html#command-line-options.

如果运行mix dialyzer --overspecs (or --specdiffs),你应该得到:

your_file.ex:6:missing_range
The type specification is missing types returned by function.

Function:
Test.validate_name/1

Type specification return types:
[{:some, binary()}]

Missing from spec:
nil

Running mix dialyzer.explain missing_range:

Function spec declares a list of types, but function returns value
outside stated range.

This error only appears with the :overspecs flag.

编辑:自 OTP 25 起,Dialyzer 将引入两个新旗帜 https://www.erlang.org/news/153#dialyzer: missing_return and extra_return,分别类似于overspecs and underspecs,但误报较少,在实践中更有用。

missing_return会抓住missing_range上面的例子,但没有返回很多噪音contract_subtype您可能并不真正关心的警告,例如overspecs does.

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

Dialyzer 无法识别使用多态类型的函数中的错误 的相关文章

随机推荐

  • C# 获取分配总数

    有没有办法获得分配总数 注意 分配数量 而不是分配的字节数 它可以是当前线程的 也可以是全局的 以更容易的为准 我想检查特定函数分配了多少个对象 虽然我了解 调试 gt 性能分析器 Alt F2 但我希望能够从程序内部以编程方式执行此操作
  • 允许 PDFium 支持 x86 和 x64

    我构建了一个 WinForms 应用程序 它使用 PDFium 来打印 PDF 文档 我从 NuGet 安装了 PDFium 它在我的项目中创建了两个子文件夹 x86 和 x64 正如预期的那样 每个子文件夹中都包含相关版本的 pdfium
  • 将均匀分布转换为正态分布

    如何将均匀分布 大多数随机数生成器产生的结果 例如在 0 0 和 1 0 之间 转换为正态分布 如果我想要我选择的平均值和标准差怎么办 方法有很多 Do not使用博克斯穆勒 特别是当你画很多高斯数时 Box Muller 产生的结果被限制
  • Django:模型类 user.models.Users 未声明显式 app_label 并且不在 INSTALLED_APPS 中的应用程序中

    姜戈版本 2 0蟒蛇 3 6 5错误 模型类 user models Users 未声明显式 app label 并且不在 INSTALLED APPS 中的应用程序中 我刚刚将模型用户添加到我的视图中 base py DJANGO APP
  • 在SQL Server 2012 TSQL中,使用XML RAW、XML AUTO和XML PATH有什么区别

    正如标题所示 欢迎所有开放的思想 我在我的电脑上测试了一下 输出似乎是一样的 例如 USE BOB DATABASE SELECT ID Name First Name Last Name FROM DBO T User FOR XML A
  • 生成字符串所有组合的算法

    我在网上找到了一个链接 其中显示了生成字符串的所有组合的算法 http www mytechinterviews com combinations of a string http www mytechinterviews com comb
  • 为什么选择源进行 SQL 架构比较会导致 VS2012 崩溃?

    似乎没有任何原因 选择 SQL gt 架构比较 gt 新架构比较 然后尝试 选择源 会导致 Visual Studio 2012 崩溃 几个月来它一直按预期工作 除了尝试重新安装之外还有其他可能的修复方法吗 注意 尝试在 Visual St
  • 如何将数据从servlet传递到android应用程序

    I have a form in android upon submit im inserting it into database using servlet i have to show to user that form was in
  • 如何在JavaScript中计算3点之间的角度? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想在 JavaScript 中获取 3 点之间的角度 如果我有积分A x1 y1 B x2 y2 and C x3 y3 我想得到由线A
  • Nightwatch.js 始终返回退出代码 1

    我尝试将 Nightwatch js 测试集成到 Jenkins 作业中 如果测试失败 我希望 Jenkins 构建失败 如果所有测试都通过 我希望构建通过 但我认识到夜巡总是返回exit code 1 测试通过或失败并不重要 但我期望ex
  • Python 转换日期格式

    给定一个像这样的字符串 2020 08 14 我如何将其转换为 14 August 2020 使用Python 3 您可以使用datetime用于重新格式化日期字符串的模块 使用strptime你可以从一个字符串读入一个datetime对象
  • 如何用 POST 替换 window.open(...)

    我目前有一些运行的代码window open urlWithGetParams 线 据我所知 这将迫使我使用GET要求 我想通过 POST 请求来完成此操作 有解决方法吗 我没有结婚window open 任何一个 我愿意接受任何允许我通过
  • 我可以换行 img 替代文本吗?

    我有一个由 css 样式设置为 100x75 的图像 当它不加载时 替代文本会加载到空间中 但会将容器扩展到超过 100 像素宽度 我怎样才能防止这种情况发生 要么把它剪掉 要么把它包起来 好吧 我在某种程度上明白了 我只是将图像包装在相同
  • QUERY Google Sheets 函数中同一字符串中的引号和撇号

    我想知道如何处理这样的查询 假设电子表格的单元格 A2 中包含以下文本 Case Bakers Flats 12 White Flour Tortillas 10 12ct 并需要将以下公式代入B2 QUERY importrange KE
  • 了解 JPA 序列生成器

    我正在使用 spring data JPA 的序列生成器将主键分配给实体 模型包含 Id GeneratedValue strategy GenerationType SEQUENCE generator seq post Sequence
  • 使用 GPUImageFilter 时发生崩溃

    我从 Github 上 Brad Larson 的教程开始 当我将这些代码添加到我的项目中时 void viewDidLoad super viewDidLoad GPUImageVideoCamera videoCamera GPUIma
  • reg 声明中的位顺序

    如果我需要使用 4 个 8 位数字 我会声明以下 reg reg 7 0 numbers 3 0 我对第一个和第二个声明 7 0 和 3 0 之间的区别感到很困惑 他们应该按什么顺序来 第一个是保留数字的大小 而第二个是保留数字的数量 还是
  • 为什么修改数组的副本会影响原始数组?

    大家好 如果这是一个菜鸟问题 我很抱歉 但我使用的是 python 我有一个问题 我复制一个数组 但当我修改副本时 它会影响原始数组 我想将边界矩阵的线性偏移添加到一组坐标 boundaries 5 818 0 0 0 0 0 0 5 81
  • TFS + 获取最新版本

    当我从 TFS 获取最新版本时 有没有办法列出已更新的文件 如果您使用的是 Visual Studio IDE 您可以在 输出 窗口中看到文件列表 要查看 输出 窗口 请选择菜单 视图 gt 输出 希望这可以帮助
  • Dialyzer 无法识别使用多态类型的函数中的错误

    背景 我正在尝试使用透析器进行多态打字 作为一个例子 我正在使用著名的Option类型 又名 Maybe Monad 现在在许多其他语言中都很流行 defmodule Test do type option t some t nothing