我正在感兴趣地阅读在线书"给你学点二郎“,并尝试一些练习来检查我的理解。
在类型规范和Erlang一章中,我对fifo示例做了一些修改,试图定义一个"typed_fifo( T)“(一个fifo,其中所有元素都必须是相同类型的T)。
我的类型说明是:
-type typed_empty_fifo() ::{fifo,[],[]} -type typed_nonempty_fifo(A):{fifo,nonempty_list(A),list(A)} {fifo,[],nonempty_list(A) } -type typed_fifo(A) ::typed_empty_fifo() x typed_nonempty_fifo(A)。
当我在以下函数规范中使用它时:
-spec空(typed_empty_fifo()) -> true; (typed_nonempty_fifo(_)) -> false. 空({fifo,[],[]}) ->真; 空({fifo,A,B})当is_list(A),is_list(B) ->假。
Dialyzer说,它将忽略规格,因为重叠的领域。
有人能告诉我哪里出错了吗?
我还有一个观点,在尝试定义输入fifo之前,我有一个运行良好的版本,一个透析器告诉我,没有什么能阻止使用不正确的列表。显然,我没有找到一种简单的方法(我可以在警卫中使用)来测试列表的适当/不适当的性质。
这真的很奇怪,因为当我使用bif长度/1时,它就会失败,原因是badarg!
水飞虱( 23> L=1,2|3. ==> )1,2~3 24> is_list(L.)==>真 25>长度(L)。==>异常错误:错误参数 在函数长度/1中称为长度(1,2/3)
谢谢
发布于 2012-08-30 19:24:02
你的类型和规格没有什么问题。问题是,在透析器中用于表示类型的数据类型并不像您所提供的那样精确。具体来说,联合:{fifo, nonempty_list(A), list(A)} | {fifo, [], nonempty_list(A)}
被“压碎”成{fifo, list(A), list(A)}
,因为元组具有相同的一致性(3)和第一个原子元素(fifo
)。透析器通常做过近似(你也可以看到这里),以使类型分析更有效。您可以安全地忽略此警告。
对于第二个问题,is_list/1
只检查作为其参数传递的术语的第一个构造函数是否为反单元格。甚至is_list([1|2])
也返回true
。
如果要确保参数是正确的列表,可以在case
表达式中使用以下自定义函数:
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.
不过,这不能放在警卫身上。在警卫中,您可以使用您在下面的评论(length(L) >= 0
)中建议的。
发布于 2012-08-30 13:49:23
关于您的第二个问题,使用list
的正确方法是:
1> L = [1,2|[3]].
[1,2,3]
2> is_list(L).
true
3> length(L).
3
注意,[Head|Tail]
表示法要求Tail
必须是list
(而不是int
)。
https://stackoverflow.com/questions/12197338
复制相似问题