如何解决请向我解释这个 Map 键类型约束配方
我是 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 的有用回答的好处进行了更多试验后,我可以看到在我的情况下不需要这个配方(从键值对列表中初始化一个不可变的 Map)。
首先,我发现如果列表的后续元素与第一个元素的类型不同,我会收到类型错误:
let things = [
("a",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",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 讨论:
What is the difference between let-bindings and references in OCaml?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。