编写这段代码后
module type TS = sig
type +'a t
end
module T : TS = struct
type 'a t = {info : 'a list}
end
我意识到我需要
info
可变。我写了,然后:
module type TS = sig
type +'a t
end
module T : TS = struct
type 'a t = {mutable info : 'a list}
end
但是,惊讶
Type declarations do not match:
type 'a t = { mutable info : 'a list; }
is not included in
type +'a t
Their variances do not agree.
哦,我记得听说过差异。这是关于协方差和矛盾的东西。我是一个勇敢的人,我一个人都会发现我的问题!
我发现了这两篇有趣的文章(here和here),我理解了!
我会写
module type TS = sig
type (-'a, +'b) t
end
module T : TS = struct
type ('a, 'b) t = 'a -> 'b
end
但是后来我想知道。可变数据类型为何不变,而不仅仅是协变?
我的意思是,我知道
'A list
可以视为('A | 'B) list
的子类型,因为我的列表无法更改。对于函数而言,如果我具有'A | 'B -> 'C
类型的函数,则可以将其视为'A -> 'C | 'D
类型的函数的子类型,因为如果我的函数可以处理'A
,而'B
则只能处理'A
的,如果我只返回'C
的,我肯定可以期望'C
或'D
的(但我只会得到'C
的)。但是对于数组?如果我有
'A array
,则不能将其视为('A | 'B) array
,因为如果我修改放置'B
的数组中的元素,则我的数组类型是错误的,因为它确实是('A | 'B) array
而不是'A array
了。但是('A | 'B) array
作为'A array
呢?是的,这很奇怪,因为我的数组可以包含'B
,但是奇怪的是我认为它与函数相同。也许到最后,我并不太了解所有内容,但我想在此发表自己的看法,因为花了我很长时间才理解它。TL; DR:
持续性:
+'a
功能:
-'a
可变的:不变量(
'a
)?为什么不能强制将其设为-'a
?
最佳答案
我认为最简单的解释是,可变值具有两个固有操作:getter和setter,它们使用字段访问和字段集语法表示:
type 'a t = {mutable data : 'a}
let x = {data = 42}
(* getter *)
x.data
(* setter *)
x.data <- 56
Getter的类型为
'a t -> 'a
,其中'a
类型变量位于右侧(因此施加了协方差约束),而setter的类型为'a t -> 'a -> unit
,类型变量位于箭头的左侧,施加了一个反约束。因此,我们拥有协变和逆变的类型,这意味着类型变量'a
是不变的。
关于ocaml - OCaml方差(+'a,-'a)和不变性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40510195/