![](/img/trans.png)
[英]How do I implement hash functions for arbitrary record types in ReScript?
[英]How would I write a generic function to handle multiple record types in ReScript?
給定以下人為的示例,是否可以編寫一個get
function 可以處理具有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))
如果沒有,object 是否可以做到這一點? 或者,處理這種情況的最佳方法是什么?
它不是。 因為記錄是名義上(而不是結構上)類型的,所以無法指定“任何帶有a
字段的記錄”。 因此get
將被推斷為具有編譯器看到的帶有a
字段的最后一個類型,即type_two
。
但是有 object 類型,它是帶有子類型的結構,允許這樣做:
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))
這個用例可能有點冗長,但這有時會派上用場。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.