gpt4 book ai didi

object - 在可扩展对象类型的情况下,我应该如何指向记录字段?

转载 作者:行者123 更新时间:2023-12-03 22:07:57 25 4
gpt4 key购买 nike

想办法在 Reason 中定义一个物体上的简单镜头。

我尝试使用以下代码使用可扩展对象(带有 .. 前置到字段列表):

type hasName('a, 't) = {.. name: 't} as 'a;
type lens('s, 'v) = {
get: 's => 'v,
set: ('s, 'v) => 's,
};
let nameLens: lens(hasName('a, 't), 't) = {
get: s => s.name,
set: (s, v) => {...s, name: v},
}

我收到“找不到记录字段名称”。错误,尽管 hasName 的类型绝对应该有一个......我在这里做错了什么?

免责声明:我对 Reason/OCaml 真的很陌生,所以我可能会错过一些明显的东西。

最佳答案

错误信息不是很好(委婉地说),但如果您仔细阅读,它确实指出了问题所在。它说“找不到 记录字段 名称。”,考虑到您拥有的是对象而不是记录,这并不奇怪。这是一个错误,因为对象成员是通过 # 访问的。 ,不是 . (见 the Reason docs on objects)。

据我了解,这样做的原因是 OCaml 不支持临时多态性(即函数或运算符重载),因此为了使类型推断正常工作,它需要在语法上区分不同类型的操作。我还怀疑它不只是说“老兄,这是一个对象,而不是记录”的原因是类型系统没有任何记录类型的概念,而是需要特定的记录类型。因此,它首先尝试查找该字段,然后识别与其关联的特定记录类型。如果找不到该字段,则不会将其视为类型错误,因为没有可与之冲突的正确类型。

在任何情况下,使用 # 就可以很容易地解决 setter/getter 问题。而不是 . .然而,二传手问题更大。在这里,您也使用了记录更新语法,并且会得到类似的错误,但不幸的是,对象没有直接的等价物。

使对象面向对象的部分原因是它们的实现是隐藏的。如果你不知道里面是什么,你就不能从外面复制一个对象。虽然您可以创建符合相同对象类型的不同对象,但只有在知 Prop 体类型的情况下才能这样做。在这种情况下你没有。

因此,不可变地更新对象的方法是从对象内部,在 setter 方法中进行,在那里您知道需要知道的一切。不可变地更新当前对象的语法是 {<name: newName>} ,仅在方法定义中有效。然后当然我们还需要将这个setter方法添加到hasName类型。

把这一切放在一起,我们最终得到这个:

type hasName('a, 't) =
{
..
name: 't,
setName: 't => 'a,
} as 'a;

type lens('s, 'v) = {
get: 's => 'v,
set: ('s, 'v) => 's,
};

let nameLens: lens(hasName('a, 't), 't) = {
get: s => s#name,
set: (s, v) => s#setName(v),
};

let obj = {
val name =
"myName";

pub name =
name;

pub setName = newName =>
{<name: newName>}
};

nameLens.set(obj, "newName")
|> nameLens.get
|> print_endline

关于object - 在可扩展对象类型的情况下,我应该如何指向记录字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56187948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com