Elixir/Erlang Dialyzer:为什么行为回调的param类型应该是子类型而不是超类型? [英] Elixir / Erlang Dialyzer : Why behaviour callback's param type should be subtype instead of supertype?

查看:90
本文介绍了Elixir/Erlang Dialyzer:为什么行为回调的param类型应该是子类型而不是超类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个行为X和一个带有参数类型的回调函数:

I have a behaviour X and a callback function with parameter type:

%{a: any}

模块Y实现行为X,而实现模块Y中的回调函数具有参数类型:

Module Y implements behaviour X and the callback function in implementing module Y has parameter type:

%{a: any, b: any}

Dialyzer不喜欢它并抱怨:

Dialyzer doesn't like that and complains:

(#{'a':=_, 'b':=_, _=>_}) 
is not a supertype of 
#{'a':=_}

这意味着透析器尝试确定实现模块Y中的回调参数的类型是否为行为X中的参数类型的超类型.换句话说,它询问:

This implies dialyzer attempts to determine if callback parameter's type in implementing module Y is a supertype of param type in behaviour X. In other words, it asks:

行为X的回调参数类型是%{a: any}的子类型吗? 实现模块Y的参数类型%{a: any, b: any}?

Is behaviour X's callback param type %{a: any} a subtype of implementing module Y's param type %{a: any, b: any}?

为什么透析仪期望行为回调的参数类型是子类型而不是超类型?

在编程语言类型理论的上下文中,定义了子类型为:

In the context of programming language type theory, subtype is defined as:

类型S是类型T的子类型,如果表达式为,则写为S< ;:T. 类型S可以在任何需要类型T的上下文中使用. 另一种表达方式是,任何类型为S的表达式都可以 假装成T型表达.

type S is a subtype of a type T, written S <: T, if an expression of type S can be used in any context that expects an element of type T. Another way of putting this is that any expression of type S can masquerade as an expression of type T.

根据以上定义,行为回调的参数类型为T而实现模块的参数类型为S对我来说很有意义.因为执行模块仍然保持行为契约.但是,我对为什么透析仪期望出现相反的情况一无所知.

In light of the definition above, it makes sense to me if parameter type of behaviour callback is T and that of implementing module is S. Because implementing module still keeps the behaviour contract. However, I'm clueless as to why dialyzer expects the other way around.

请帮助我理解这一点.

注意:此问题是后续问题,但独立于另一个SO问题 Erlang( Elixir)Dialyzer-令人困惑的超类型错误.

Note: This question is a follow-up but independent of another SO question Erlang (Elixir) Dialyzer - confusing supertype error.

推荐答案

Dialyzer是正确的.如果存在具有%{a: any}类型的回调的行为X,则用户应能够调用声称实现此行为的任何模块的该函数,例如%{a: 1}.模块的函数采用%{a: any, b: any},它是%{a: any}子类型,这意味着该函数不能再用%{a: 1}调用,这与行为不符.

Dialyzer is correct. If there is a behaviour X with a callback of type %{a: any}, the user should be able to call that function of any module that claims to implement this behaviour with e.g. %{a: 1}. Your module's function takes %{a: any, b: any} which is a subtype of %{a: any}, which means that function cannot be called with %{a: 1} anymore which does not comply with the behaviour.

另一方面,如果行为的回调的类型为%{a: any, b: any},而您的模块的函数的类型为%{a: any},那会很好,因为%{a: any}%{a: any, b: any}的超类型,并且您的模块可以是用%{a: 1, b: 2}调用-它可以忽略多余的字段.

On the other hand, if the behaviour's callback had the type %{a: any, b: any} and your module's function had the type %{a: any}, that would have been fine because %{a: any} is a supertype of %{a: any, b: any} and your module can be called with %{a: 1, b: 2} -- it can just ignore the extra field.

这篇关于Elixir/Erlang Dialyzer:为什么行为回调的param类型应该是子类型而不是超类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆