8

我有一个没有代码的项目-spec-type目前dialyzer可以找到一些警告,其中大部分是机器生成的代码。

将类型规范添加到代码中会使透析器发现更多错误吗?

题外话,有没有工具可以检查是否违反了规范?

4

1 回答 1

11

添加 typespecs 将显着提高 Dialyzer 的准确性。

因为 Erlang 是一种动态语言,所以 Dialyzer 必须默认对类型进行相当广泛的解释,除非你提示它缩小它所经历的“成功”类型。可以把它想象成给 Dialyzer 一个过滤器,通过它它可以将一组可能的成功转换为应该工作的显式类型的子集。

这与 Haskell 不同,后者的默认假设是失败,并且所有代码都必须使用成功的类型编写才能被编译—— Dialyzer 必须默认假设成功,除非它确定某个类型将失败。

Typespecs 是其中的主要部分,但 Dialyzer 也检查守卫,所以一个函数像

increment(A) -> A + 1.

不一样

increment(A) when A > 100 -> A + 1.

虽然两者都可以输入为

-spec increment(integer()) -> integer().

大多数时候您只关心整数值是integer(), pos_integer(), neg_integer(), or non_neg_integer(),但有时您需要一个仅在一侧有界的任意范围——而类型语言目前无法表示这一点(尽管我个人希望看到一个100..infinity预期的工作声明)。

的无界范围when A > 100需要一个守卫,但是像这样的有界范围when A > 100 and A < 201可以单独在 typespec 中表示:

-spec increment(101..200) -> pos_integer().
increment(A) -> %stuff.

除了调用之外,守卫速度很快length/1(在守卫中你可能永远不需要它),所以在你真正知道并且可以证明你有一个来自守卫的性能问题之前,不要担心性能开销。使用守卫类型规范来约束 Dialyzer 非常有用。它作为自己的文档也非常有用,特别是如果您使用 edoc,因为 typespec 将显示在那里,使 API 不那么神秘,并且一目了然。

有一些关于在现有代码库中使用 Dialyzer 的有趣文献。这里有一个有据可查的体验:Erlang 程序的渐进式输入:牧马人体验。(不幸的是,我以前从中学到很多的其他一些链接已经消失或移动了。(!.!)仔细阅读 Wrangler 论文,浏览用户指南手册页,使用 Dialyzer,以及之前的一些经验不过,像 Haskell 之类的类型系统不仅可以让您为从 Dialyzer 获得大量里程做好准备。)

[顺便说一句,我之前和几个人谈过关于指定“纯”函数的问题,这些函数可以用符号或使用不同的定义语法来保证强类型(可能是 Prolog 的:-而不是 Erlang 的->......或其他东西) ),但是尽管那会很酷,而且即使是现在也很有可能将副作用集中在程序的一小部分并将所有结果传递回 的元组中{Results, SideEffectsTODO},这根本不是一个紧迫的需求,而且 Erlang 工作得非常好照原样。但 Dialyzer 确实非常有助于向您展示您在哪里迷失了自己!]

于 2015-12-21T08:00:35.820 回答