药剂/二郎透析:为什么行为回调的参数类型应该是子类型,而不是超?(Elixir / Erlang D

2019-09-27 02:59发布

我有一个行为X与参数类型回调函数:

%{a: any}

模块Y实现行为X和在执行模块Y具有参数类型的回调函数:

%{a: any, b: any}

透析不喜欢和抱怨:

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

这意味着透析器试图确定是否回调参数在执行模块Y型的参数类型的行为X.换句话说超类型,它要求:

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

为什么透析预期行为回调的参数类型是一个亚型,而不是一个超?

在编程语言类型理论的情况下, 子类型被定义为:

类型S是类型T的子类型,s要写的<:T,如果S型的表达可以在一个期望的另一种方式把这个的类型T的元素的任何上下文中使用的是S型的任何表达可以伪装为类型T的表达

在上面的定义的光,是有意义的我,如果参数类型的行为回调是T和实现模块的是S 。 因为实现模块仍保持行为的合同。 不过,我无能,为什么透析预计,周围的其他方法。

请帮我理解这一点。

注意:这个问题是一个跟进,但独立的另一SO质疑二郎(药剂)透析-混淆超错误 。

Answer 1:

透析是正确的。 如果有一个行为X与类型的回调%{a: any} ,用户应该能够调用声称实现与如该行为的任何模块的该功能%{a: 1} 你的模块的功能需要%{a: any, b: any}这是一个亚型 %{a: any} ,这意味着功能不能用所谓的%{a: 1}了不符合的行为。

在另一方面,如果该行为的回调有类型%{a: any, b: any}和你的模块的功能已经类型%{a: any} ,那会是很好的,因为%{a: any}是的超类型%{a: any, b: any}和你的模块可以被称为%{a: 1, b: 2} -它可以直接忽略额外的领域。



文章来源: Elixir / Erlang Dialyzer : Why behaviour callback's param type should be subtype instead of supertype?