我根据本教程创建了下面的代码片段。最后两行 (feed_squid(FeederRP)
和feed_red_panda(FeederSquid)
) 显然违反了定义的约束,但 Dialyzer 发现它们没问题。这非常令人失望,因为这正是我想要使用执行静态分析的工具捕获的错误类型。
教程中提供了一个解释:
在使用错误类型的馈线调用函数之前,首先使用正确的类型调用它们。从 R15B01 开始,Dialyzer 不会发现此代码有错误。观察到的行为是,只要在函数体内成功调用给定函数,Dialyzer 就会忽略同一代码单元中的后续错误。
这种行为的理由是什么?我知道成功打字背后的哲学是“永远不要哭狼”,但在当前情况下,Dialyzer 显然忽略了有意定义的函数规范(在它看到函数已被正确调用之后)。我了解该代码不会导致运行时崩溃。我能以某种方式强迫 Dialyzer 始终认真对待我的功能规范吗?如果没有,是否有工具可以做到这一点?
-module(zoo).
-export([main/0]).
-type red_panda() :: bamboo | birds | eggs | berries.
-type squid() :: sperm_whale.
-type food(A) :: fun(() -> A).
-spec feeder(red_panda) -> food(red_panda());
(squid) -> food(squid()).
feeder(red_panda) ->
fun() ->
element(random:uniform(4), {bamboo, birds, eggs, berries})
end;
feeder(squid) ->
fun() -> sperm_whale end.
-spec feed_red_panda(food(red_panda())) -> red_panda().
feed_red_panda(Generator) ->
Food = Generator(),
io:format("feeding ~p to the red panda~n", [Food]),
Food.
-spec feed_squid(food(squid())) -> squid().
feed_squid(Generator) ->
Food = Generator(),
io:format("throwing ~p in the squid's aquarium~n", [Food]),
Food.
main() ->
%% Random seeding
<<A:32, B:32, C:32>> = crypto:rand_bytes(12),
random:seed(A, B, C),
%% The zoo buys a feeder for both the red panda and squid
FeederRP = feeder(red_panda),
FeederSquid = feeder(squid),
%% Time to feed them!
feed_squid(FeederSquid),
feed_red_panda(FeederRP),
%% This should not be right!
feed_squid(FeederRP),
feed_red_panda(FeederSquid).