Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Erlang:在代码中添加类型规范会使透析器更有效吗?_Erlang_Dialyzer - Fatal编程技术网

Erlang:在代码中添加类型规范会使透析器更有效吗?

Erlang:在代码中添加类型规范会使透析器更有效吗?,erlang,dialyzer,Erlang,Dialyzer,我有一个项目,代码中没有-spec或-type,目前透析器可以找到一些警告,其中大部分是机器生成的代码 将类型规格添加到代码中会使透析器发现更多错误吗 在主题之外,是否有任何工具来检查是否违反了规范?添加TypeSpec将显著提高透析器的准确性 因为Erlang是一个动态语言透析器,除非您提示它缩小“成功”类型的范围,否则它必须默认使用相当广泛的类型解释。把它想象成给透析器一个过滤器,通过它可以将一组可能的成功转化为一组应该可以工作的显式类型 这与Haskell不同,Haskell的默认假设是失

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

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

在主题之外,是否有任何工具来检查是否违反了规范?

添加TypeSpec将显著提高透析器的准确性

因为Erlang是一个动态语言透析器,除非您提示它缩小“成功”类型的范围,否则它必须默认使用相当广泛的类型解释。把它想象成给透析器一个过滤器,通过它可以将一组可能的成功转化为一组应该可以工作的显式类型

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

类型规格是这项工作的主要部分,但透析器也会检查防护装置,所以类似于

increment(A) -> A + 1.
不一样

increment(A) when A > 100 -> A + 1.
虽然两者都可以按

-spec increment(integer()) -> integer().
大多数时候,您只关心整数值是
integer()
pos\u integer()
neg\u integer()
,还是
non\u neg\u integer()
,但有时您需要一个仅在一侧有界的任意范围,而类型语言目前无法表示这一点(尽管就我个人而言,我希望看到
100..infinity
的声明能如预期那样发挥作用)

当A>100需要保护时,
的无界范围需要保护,但是当A>100和A<201
时,
的有界范围可以单独在typespec中表示:

-spec increment(101..200) -> pos_integer().
increment(A) -> %stuff.
除了调用
length/1
(您可能永远都不需要在一个守卫中调用)之外,守卫速度很快,因此,在您真正了解并能够证明您存在来自防护装置的性能问题之前,不要担心性能开销。使用防护装置和typespec约束透析器非常有用。它对于您自己来说也是非常有用的文档,尤其是当您使用edoc时,因为typespec将在此处显示,使API不那么神秘,一眼就能玩弄

关于透析器在现有代码库中的使用,有一些有趣的文献。这里有一个详细记录的经验:。(不幸的是,我从以前学到的很多其他链接已经消失或移动了。(!)不过,仔细阅读牧马人的论文,浏览和,玩透析器,以及之前在Haskell这样的打字系统中的一些经验,将为你从透析器中获得更多的里程做好准备。)


[顺便说一句,我之前和一些人谈过如何指定“纯”函数,这些函数可以通过符号或使用不同的定义语法(可能是Prolog的
:-
而不是Erlang的
->
…或其他东西)保证为强类型函数),但尽管这很酷,而且即使现在也很有可能将副作用集中在程序的一小部分,并将所有结果返回到
{results,SideEffectsTODO}元组中
,这并不是一个迫切的需求,Erlang的工作也非常好。但是透析器确实非常有助于告诉你你在哪里迷失了自我!]

谢谢你的详细回答:)在问这个问题之前,我在代码库中添加了一些规范,这没有任何帮助,我猜我加的太少了,或者加了一些无关紧要的部分(透析器准确猜测的部分)。我仍然怀念Haskell的类型系统:(@NotanID我也怀念它!这就是为什么我想有一种方法来声明编译器强制的严格/纯函数。总的来说,Erlang方法在产生过程中的好处是非常巨大的(而且你不会得到随机构建失败,因为本周有人在阴谋集团中玩弄了禁止的秘密),但如果有一些强制的纯定义方法或一种形式化的monadizing操作方法,以及延迟的副作用煎饼(如
{Values,TODOs}
),透析器或编译器知道如果它闻起来很好笑,就会抱怨它(嗯……臭烘烘的煎饼类型系统)话虽如此,透析器本身也擅长于确定类型。我建议只使用
typer
工具添加特定的类型规格,以确定透析器无法识别类型的地方。我个人认为,过多的类型规格会使代码更难阅读。@AdamLindberg绝对是!在小型项目上(一点点Erlang实际上能走多远真是令人惊讶)我有时只使用TypeSpec作为自己的文档,关于我想写的函数,我在脑海中布局代码。但是!在一些更大的项目上(游戏服务器或业务应用程序服务等)我发现类型规范非常有用——可能存在一些相当长的值传递和操作链。@NotanID需要对运行时进行更改,这些更改与Erlang的工作方式(并且一直都是这样)不兼容.Dynamic类型对于我们期望正常工作的许多运行时功能是必需的。但是,将纯声明作为单独的语言语义添加是完全可能的。而且我们希望在Erlang中产生副作用——这种完整的并发方式是基于消息传递的,而不是调用。