【问题标题】:How would I write a generic function to handle multiple record types in ReScript?我将如何编写一个通用函数来处理 ReScript 中的多种记录类型?
【发布时间】:2021-02-16 16:39:33
【问题描述】:

鉴于以下人为设计的示例,是否可以编写一个get 函数来处理具有a 属性的任何记录?

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

如果不是,这可能与对象有关吗?或者,处理这种情况的最佳方法是什么?

【问题讨论】:

  • 格伦的回答很全面。恕我直言,“最好的方法”真的取决于你的具体情况,所以真的很难说。如果我们纯粹从理论上讨论,那么使用对象类型似乎是显而易见的解决方案。

标签: reason bucklescript rescript


【解决方案1】:

不是。因为记录是名义上(而不是结构上)类型的,所以无法指定“任何带有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))

但请注意,使用对象而不是记录需要权衡取舍,例如无法以模式解构它们。

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

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))

这个用例可能有点冗长,但这有时会派上用场。

【讨论】:

  • 好答案。一个更正:ReScript 支持一流的模块。
  • 啊,确实是@Yawar。它似乎没有记录在案,我无法弄清楚它的语法,但我现在看到它记录在Advanced->Supported Types 下。答案已更新。感谢您的提醒!
  • 哦,对了,它实际上记录在 genType 下,可能是因为它是从 Cristiano 的原始 genType 文档中复制过来的
  • 我也错过了文档的这一部分。这个问题源于一个 JS compat 问题。感谢您的帮助。
猜你喜欢
  • 2016-03-28
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多