Types 为什么透析器告诉我这个有趣的合同有重叠的领域?

Types 为什么透析器告诉我这个有趣的合同有重叠的领域?,types,erlang,dialyzer,Types,Erlang,Dialyzer,我正在饶有兴趣地阅读在线书籍“”,并尝试一些练习来检查我的理解 我对fifo示例进行了一些修改,在类型规范和Erlang一章中,试图定义“类型化的fifo(T)”(所有元素必须是相同类型的T的fifo) 我的型号规格是: -键入类型为_empty_fifo()::{fifo,[],[]} -输入类型为{fifo,非空列表(A),列表(A)}{fifo,[],非空列表(A)} -类型类型化的fifo(A)::类型化的空的fifo();类型化的非空的fifo(A) 当我在以下函数规范中使用它时: -

我正在饶有兴趣地阅读在线书籍“”,并尝试一些练习来检查我的理解

我对fifo示例进行了一些修改,在类型规范和Erlang一章中,试图定义“类型化的fifo(T)”(所有元素必须是相同类型的T的fifo)

我的型号规格是:

-键入类型为_empty_fifo()::{fifo,[],[]}

-输入类型为{fifo,非空列表(A),列表(A)}{fifo,[],非空列表(A)}

-类型类型化的fifo(A)::类型化的空的fifo();类型化的非空的fifo(A)

当我在以下函数规范中使用它时:

-spec empty(typed_empty_fifo())->true

空({fifo,[],[]})->true

当is_list(A)和is_list(B)->false时为空({fifo,A,B})

透析器告知,由于域重叠,它将忽略该规范

有人能告诉我哪里出错吗

我还有一点,在尝试定义类型化fifo之前,我有一个运行良好的版本,一个透析器告诉我没有什么可以阻止使用不正确的列表。令人惊讶的是,我没有找到一种简单的方法(我可以在一个守卫中使用)来测试列表的正确/不正确字符

这真的很奇怪,因为当我使用bif length/1时,它会失败,原因是badarg

23>L=[1,2|3]。=>[1,2 | 3]

24>是列表(L)。==>真的

25>长度(L)。==>异常错误:参数错误

 in function  length/1

    called as length([1,2|3])

谢谢

关于第二个问题,正确使用
列表的方法是:

1> L = [1,2|[3]].
[1,2,3]
2> is_list(L).
true
3> length(L).
3

请注意,
[Head | Tail]
符号要求
Tail
成为
list
(而不是
int
)。

您的类型和规范没有任何问题。问题是透析器中用于表示类型的数据类型没有保持您提供的精度。具体地说,联合:
{fifo,nonempty_list(A),list(A)}{fifo,[],nonempty_list(A)}
被“压碎”成
{fifo,list(A),list(A)}
,因为元组具有相同的算术(3)和第一个原子元素(
fifo
)。透析器通常会进行过度近似(正如您也可以看到的),以使类型分析更有效。您可以放心地忽略此警告

对于第二个问题,
is_list/1
仅检查作为参数传递的术语的第一个构造函数是否为cons单元格。偶数
is_list([1 | 2])
返回
true

如果要确保参数是正确的列表,可以在
案例
表达式中使用自定义函数,如下所示:

case is_proper_list(L) of
  true -> ...;
  false -> ...
end

is_proper_list([]) -> true;
is_proper_list([_|L]) -> is_proper_list(L);
is_proper_list(_) -> false.

但是,这不能放在防护装置中。在guards中,您可以使用您在下面的评论中建议的选项(
length(L)>=0
)。

谢谢您的回答。我知道,但我写问题的结尾可能太快了。我是故意做这个作业的,为了创建一个不合适的列表。事实上,我的fifo模块将只创建有效的fifo,但没有什么可以阻止另一个模块创建基于不正确列表的fifo,我想检查它(为了练习,当然,在现实生活中我使用sdlib one…),谢谢Aronis。我想我的要求比透析器打算提供的要多。我正试图弄清楚使用这些规范定义的好处是什么,透析器能做什么,对我来说是什么。至少我发现这个问题的列表不正确。顺便说一下,我仍在寻找第二个问题的解决方案。我发现一个有趣的测试,比如:is_list(X)和also length(X)>-1是有效的。但是它在一个函数中崩溃了。我已经用一个可能的解决方案编辑了答案。哦,我的名字是斯塔夫罗斯!:-)
case is_proper_list(L) of
  true -> ...;
  false -> ...
end

is_proper_list([]) -> true;
is_proper_list([_|L]) -> is_proper_list(L);
is_proper_list(_) -> false.