【发布时间】:2017-01-02 11:49:39
【问题描述】:
我想在实例化通用记录时显式提供类型参数。换句话说,给定一个RecordType<'T1, 'T2, 'T3>,我想通过指定这些通用参数来创建一个带有一些固定'T1、'T2 和'T3 的RecordType<'T1, 'T2, 'T3> 实例。有没有办法在 F# 中做到这一点?
我看到了三种有用的情况:
-
当有多个同名泛型类型时实例化记录
假设我们有以下记录定义:
type SimpleGenericRecord<'T1, 'T2> = { f1 : 'T1 -> 'T2 } type SimpleGenericRecord<'T> = { f1 : 'T -> 'T }我很容易构造
SimpleGenericRecord<'T>的实例,它是 最后定义:let record = { f1 = fun (x: int) -> 0 } let record1 = { SimpleGenericRecord.f1 = fun (x: int) -> 0 }以下尝试创建
SimpleGenericRecord<int, int>编译错误:let record2 = { SimpleGenericRecord<int, int>.f1 = fun (x: int) -> 0 } let record3 = { SimpleGenericRecord<_, _>.f1 = fun (x: int) -> 0 }我知道为两种类型使用相同的记录名称可能不是最好的主意,但是,我认为语言应该为我提供一种使用两种类型的方法。
-
记录记录类型
F# reference 说:
不要对记录字段使用 DefaultValue 属性。一个更好的 方法是定义具有字段的记录的默认实例 初始化为默认值,然后使用复制和更新 记录表达式以设置与默认值不同的任何字段 价值观。
根据那条建议,我想定义记录的默认实例,并且由于它们是公共 API 的一部分,因此记录它们的类型。
-
有助于类型推断
记录类型的通用参数可用于推断记录值的类型。
假设我有:
type RecordWithSomeComplexType<'T> = { t1 : int -> System.Collections.Generic.Dictionary<int, 'T> // some long type signature }我想实例化它。如果我不提供任何类型注释,记录值将尽可能通用,例如
let record4 = { RecordWithSomeComplexType.t1 = failwith "Intentionally failing" }有类型
int -> System.Collections.Generic.Dictionary<int, obj>我可以强制记录为特定类型(例如
RecordWithSomeComplexType<string>),但在这种情况下,我需要编写特定值的完整类型,例如let failing = { RecordWithSomeComplexType.t1 = failwith "Intentionally failing" :> int -> System.Collections.Generic.Dictionary<int, string> // I don't want to provide a full type of a value here }如果编译器知道我想
RecordWithSomeComplexType<string>,它可以推断出值的签名。
【问题讨论】:
-
你得到什么编译错误?
-
@FyodorSoikin "字段绑定必须采用 'id = expr;' 的形式。
标签: generics f# algebraic-data-types