请向我解释这个 Map key-type constraint recipe
Please explain this Map key-type constraint recipe to me
我是 OCaml 和此类语言的新手。
我一直在试验 Map
,结果是:
type thing = ThingA | ThingB
module ThingMap = Map.Make(String)
let things = [
("a", ThingA);
("b", ThingB)
] |> List.to_seq
|> ThingMap.of_seq
到目前为止一切顺利,我得到了字符串到事物的映射。
然后我读到 Map.Make(String)
只强制执行键的类型,值可以是任何类型。
我找到了强制值应为 thing
类型的方法:
let m: thing ThingMap.t ref = ref ThingMap.empty
这个食谱似乎很有用,但我不明白它是如何工作的。
三个问题:
m
代表什么?它有 type thing ThingMap.t ref
类型,但这对我来说意义不大……它有什么用吗?我可以将它重命名为 _
吗?
- 是否在模块中声明它会强制约束任何模块中
ThingMap
的所有实例? (“实例”这个词正确吗?)
ref
和 empty
怎么了?这是如何工作的?
更新
在利用@Jeffrey Scofield 的有用回答进行了更多试验后,我发现我的情况不需要这个方法(从键值对列表初始化不可变映射)。
首先,我观察到如果列表的后续元素与第一个元素的类型不同,我会收到类型错误:
let things = [
("a", ThingA);
("b", 123)
] |> List.to_seq
|> ThingMap.of_seq
Error: This expression has type int but an expression was expected of type
thing
很酷,但这还不够,因为如果“错误”元素位于第一个位置,我会得到我想要的约束的“错误”类型错误:
let things = [
("a", 123);
("b", ThingB)
] |> List.to_seq
|> ThingMap.of_seq
Error: This expression has type thing but an expression was expected of type
int
我可以通过了解 let m: thing ThingMap.t ...
中冒号后面的部分是类型签名来解决这个问题,因此我可以通过向 things
添加签名来获得我想要的结果:
let things: thing ThingMap.t = [
("a", 123);
("b", ThingB)
] |> List.to_seq
|> ThingMap.of_seq
Error: This expression has type int but an expression was expected of type
thing
此处第一项类型错误,但我得到了我想要的类型错误。
m
是由let
声明的全局变量(名称)。这并不是所有 ThingMap
类型的值都包含 thing
类型的值的笼统声明。它只是一个这样的地图的声明(通过引用访问)。您稍后可以将 ThingMap.t
与任何类型的值一起使用。
# let m : thing ThingMap.t ref = ref ThingMap.empty;;
val m : thing ThingMap.t ref = {contents = <abstr>}
# let n : int ThingMap.t ref = ref ThingMap.empty;;
val n : int ThingMap.t ref = {contents = <abstr>}
这里我声明了一个值m
,一个从字符串到事物的映射的引用。然后我声明了一个值n
,一个从字符串到整数的映射的引用。
let
左边是一个图案。您当然可以使用 _
作为此模式,但这样您就没有名称来引用您的地图。
除了特定变量 m
.
,此声明不对任何内容强制执行任何约束
如果您不知道什么是引用,则应该了解它们。本质上,引用是一个可变单元格,它始终包含一种类型的值,但可以修改它以包含该类型的不同值。 (另一方面,开始使用 OCaml 时尝试不使用引用进行编码是很好的。)
ThingMap.empty
是一个没有键(因此没有值)的映射。
如果你真的想控制ThingMap
中使用的值,你可以在一个模块中定义它,为访问地图的函数指定类型。一旦将 ThingMap.t
定义为可见类型,就无法更改其含义以使其更受限制。
如果您只想为从字符串到事物的映射类型取一个方便的名称,您可以给它起一个名字:
type thingmap = thing ThingMap.t
更新
这是之前关于 OCaml(不可变)变量绑定和引用的 SO 讨论:
我是 OCaml 和此类语言的新手。
我一直在试验 Map
,结果是:
type thing = ThingA | ThingB
module ThingMap = Map.Make(String)
let things = [
("a", ThingA);
("b", ThingB)
] |> List.to_seq
|> ThingMap.of_seq
到目前为止一切顺利,我得到了字符串到事物的映射。
然后我读到 Map.Make(String)
只强制执行键的类型,值可以是任何类型。
我找到了强制值应为 thing
类型的方法:
let m: thing ThingMap.t ref = ref ThingMap.empty
这个食谱似乎很有用,但我不明白它是如何工作的。
三个问题:
m
代表什么?它有type thing ThingMap.t ref
类型,但这对我来说意义不大……它有什么用吗?我可以将它重命名为_
吗?- 是否在模块中声明它会强制约束任何模块中
ThingMap
的所有实例? (“实例”这个词正确吗?) ref
和empty
怎么了?这是如何工作的?
更新
在利用@Jeffrey Scofield 的有用回答进行了更多试验后,我发现我的情况不需要这个方法(从键值对列表初始化不可变映射)。
首先,我观察到如果列表的后续元素与第一个元素的类型不同,我会收到类型错误:
let things = [
("a", ThingA);
("b", 123)
] |> List.to_seq
|> ThingMap.of_seq
Error: This expression has type int but an expression was expected of type
thing
很酷,但这还不够,因为如果“错误”元素位于第一个位置,我会得到我想要的约束的“错误”类型错误:
let things = [
("a", 123);
("b", ThingB)
] |> List.to_seq
|> ThingMap.of_seq
Error: This expression has type thing but an expression was expected of type
int
我可以通过了解 let m: thing ThingMap.t ...
中冒号后面的部分是类型签名来解决这个问题,因此我可以通过向 things
添加签名来获得我想要的结果:
let things: thing ThingMap.t = [
("a", 123);
("b", ThingB)
] |> List.to_seq
|> ThingMap.of_seq
Error: This expression has type int but an expression was expected of type
thing
此处第一项类型错误,但我得到了我想要的类型错误。
m
是由let
声明的全局变量(名称)。这并不是所有 ThingMap
类型的值都包含 thing
类型的值的笼统声明。它只是一个这样的地图的声明(通过引用访问)。您稍后可以将 ThingMap.t
与任何类型的值一起使用。
# let m : thing ThingMap.t ref = ref ThingMap.empty;;
val m : thing ThingMap.t ref = {contents = <abstr>}
# let n : int ThingMap.t ref = ref ThingMap.empty;;
val n : int ThingMap.t ref = {contents = <abstr>}
这里我声明了一个值m
,一个从字符串到事物的映射的引用。然后我声明了一个值n
,一个从字符串到整数的映射的引用。
let
左边是一个图案。您当然可以使用 _
作为此模式,但这样您就没有名称来引用您的地图。
除了特定变量 m
.
如果您不知道什么是引用,则应该了解它们。本质上,引用是一个可变单元格,它始终包含一种类型的值,但可以修改它以包含该类型的不同值。 (另一方面,开始使用 OCaml 时尝试不使用引用进行编码是很好的。)
ThingMap.empty
是一个没有键(因此没有值)的映射。
如果你真的想控制ThingMap
中使用的值,你可以在一个模块中定义它,为访问地图的函数指定类型。一旦将 ThingMap.t
定义为可见类型,就无法更改其含义以使其更受限制。
如果您只想为从字符串到事物的映射类型取一个方便的名称,您可以给它起一个名字:
type thingmap = thing ThingMap.t
更新
这是之前关于 OCaml(不可变)变量绑定和引用的 SO 讨论: