ocaml - OCaml方差(+'a,-'a)和不变性

标签 ocaml covariance contravariance invariance

编写这段代码后

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.

哦,我记得听说过差异。这是关于协方差和矛盾的东西。我是一个勇敢的人,我一个人都会发现我的问题!
我发现了这两篇有趣的文章(herehere),我理解了!
我会写
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/

相关文章:

f# - 将 OCaml 代码转换为 F#

types - 使用 pretty-print 从值中获取字符串

来自类型定义的ocaml eval函数

c# - 在 C# 中,如何在给定 List<Object> 时确定对象的类型?

c# - 为什么 List<T> 在协变接口(interface) MyInterface<out T> 上无效

ocaml - OCaml最近几年有没有获得任何严重晋升?

java - 在方法覆盖中使用子类型作为参数

c# - C# 4.0 中协变和逆变的良好现实用例示例?

function - 为什么Function [-A1,…,+ B]与允许任何父类(super class)型作为参数无关?

c# - 对 "Already defines a member with the same parameter types"错误感到困惑