gpt4 book ai didi

reason - 我如何编写一个通用函数来处理 ReScript 中的多种记录类型?

转载 作者:行者123 更新时间:2023-12-02 18:55:34 26 4
gpt4 key购买 nike

考虑到以下人为的示例,是否可以编写一个可以处理具有 a 属性的任何记录的 get 函数?

type type_one = {a: int}
type type_two = {a: int, b: int}

let example_one = {a: 1}
let example_two = {a: 1, b: 2}

let get = record => record.a

Js.log(get(example_one)) // notice the error here
Js.log(get(example_two))

ReScript Playground

如果不是,这可以用对象实现吗?或者,处理这种情况的最佳方法是什么?

最佳答案

事实并非如此。因为记录是名义上(而不是结构上)类型的,所以无法指定“任何带有 a 字段的记录”。因此,get 将被推断为编译器在 a 字段中看到的最后一个类型,即 type_two

然而,对象类型是具有子类型的结构,允许这样做:

type type_one = {"a": int}
type type_two = {"a": int, "b": int}

let example_one = {"a": 1}
let example_two = {"a": 1, "b": 2}

let get = (record) => record["a"]


Js.log(get(example_one)) // notice no error here
Js.log(get(example_two))

但请注意,使用对象而不是记录存在一些权衡,例如无法以模式解构它们。

此外,作为旁注,在某些语言中实现这一点的另一种方法是通过临时多态性,通过显式定义附加到特定类型的公共(public)接口(interface)和实现(在 Haskell 中称为类型类,在 Rust 中称为特征)。不幸的是,Rescript 和 OCaml 目前也不支持这一点,尽管有一个以模块化隐式形式存在的 OCaml 提案。但是,您仍然可以使用模块定义通用接口(interface)和实现,并显式传递它们:

type type_one = {a: int}
type type_two = {a: int, b: int}

let example_one = {a: 1}
let example_two = {a: 1, b: 2}

module type S = {
type t
let getA: t => int
}

module T1 = {
type t = type_one
let getA = (record: t) => record.a
}

module T2 = {
type t = type_two
let getA = (record: t) => record.a
}

let get = (type a, module(T: S with type t = a), record: a) => T.getA(record)

Js.log(get(module(T1), example_one)) // notice no error here
Js.log(get(module(T2), example_two))

对于这个用例来说可能有点冗长,但这有时确实会派上用场。

关于reason - 我如何编写一个通用函数来处理 ReScript 中的多种记录类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66202957/

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