Erlang(Elixir)Dialyzer-令人困惑的超类型错误 [英] Erlang (Elixir) Dialyzer - confusing supertype error
问题描述
我已经定义了Elixir行为 X
。回调 start_link
指定为:
I have defined an Elixir behaviour X
. A callback start_link
is spec'ed as:
@callback start_link(
args :: producer_args,
opts :: GenServer.options
) :: GenServer.on_start
其中 producer_args
类型定义为:
@type producer_args :: %{job_queue_name: String.t}
在客户端代码 Y
实现该行为, start_link
定义为:
In the client code Y
that implements the behaviour, start_link
is defined as:
def start_link(args = %{job_queue_name: _job_queue_name, redis_url: _redis_url}, opts) do
GenStage.start_link(__MODULE__, args, opts)
end
Dialyzer不喜欢它。它说,
Dialyzer doesn't like it. It says,
(#{'job_queue_name':=_, 'redis_url':=_, _=>_})
is not a supertype of
#{'job_queue_name':=binary()}
问题1:
在继承方面,子类型扩展了超类型。因此,定义的行为(X)应该被视为超类型。实现行为(Y)的模块应视为子类型。显然Dialyzer应该提出这样的问题:
Question #1:
In terms of inheritance, subtypes extend supertypes. Therefore, the defined behaviour(X) should be considered supertype. Module implementing the behaviour(Y) should be considered subtype. Apparently Dialyzer should have asked the question:
是
#{'job_queue_name':= binary()}
的超类型(#{'job_queue_name':= _,'redis_url':= _,_ => _})
?
相反,它反过来问了一个问题。为什么?
Rather it asks the question the other way around. Why?
超类型的定义$透析器中的c $ c>与OOP继承中的讨论相同吗?如果没有,那是什么?我试图在透析器的上下文中找到超类型的定义,但没有找到。
Is the definition of supertype
in dialyzer the same as in discussion of OOP inheritance? If not, what is it then? I tried to find definition of supertype in the context of dialyzer but found none.
推荐答案
该错误消息基本上是在说:您不能需要额外的 redis_url
键,因为它不是在行为的类型规范中声明的。
The error message is basically saying: You cannot require the additional redis_url
key, since it was not declared in the type spec of the behaviour.
Dialyzer不会t将行为和实现模块视为类型。
专门查看回调的参数。
Dialyzer doesn't treat the behaviour and implementing module as types. It is specifically looking at the parameter to the callback.
将与#{'job_queue_name'相匹配的一组值: = _,'redis_url':= _,_ => _}
是将与#{'job_queue_name':= _} 匹配的值的子集code>。
所以#{'job_queue_name':= _,'redis_url':= _,_ => _}
是#{'job_queue_name':= _}
的子类型。
Dialyzer将允许您使用与回调中声明的参数超类型的参数来实现回调,因为这可以确保依赖行为协定的任何代码在运行时不会因匹配错误而失败。
Dialyzer will permit you to implement a callback with parameters that are supertypes of what was declared in the callback, since that ensures any code relying on the behaviour contract won't fail with a match error at runtime.
这篇关于Erlang(Elixir)Dialyzer-令人困惑的超类型错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!