内联函数和类型扩展
Inline function and type extension
假设我有两个不同的 library 类型:
type Foo = { foo : string }
type Bar = { bar : int32 }
我想实现适用于 Foo
或 Bar
实例的通用函数 zoo
。 而且我无法更改 Foo
和 Bar
,因为它们是库代码的一部分。
这是我第一次尝试使用类型扩展和内联函数 here:
// Library.fs
module Library
type Foo = { foo : string }
type Bar = { bar : int32 }
// Program.fs
type Foo with
static member zoo (f : Foo) = "foo"
type Bar with
static member zoo (b : Bar) = "bar"
let inline zoo (x : ^t) =
(^t : (static member zoo : ^t -> string) x)
let f = zoo { foo = "1" } // error FS0001: The type 'Foo' does not support the operator 'zoo'
为什么内联函数定义不依赖于类型扩展?如何在不更改初始 Foo
和 Bar
类型定义的情况下解决我的问题?
到目前为止我能得到的最好的东西是
type Ext =
static member zoo (f : Foo) = "foo"
static member zoo (b : Bar) = "bar"
let f = Ext.zoo { foo = "1" } // "foo"
let b = Ext.zoo { bar = 2 } // "bar"
这不是最好的解决方案,也不是很通用,但至少它有效。
使用方法重载。
扩展方法的问题是在 solving member constraints 时没有考虑到扩展方法。
因此您可以使用方法重载,如您自己的答案中所示,或者您可以更进一步,通过使用中间类型和中间方法(在本例中为简单起见,使用运算符)来创建内联泛型函数诀窍:
type T = T with
static member ($) (T, x:Foo) = "foo"
static member ($) (T, x:Bar) = "bar"
let inline zoo x = T $ x
let f = zoo { foo = "1" }
这里有 more details 其工作原理。
请注意,此函数将被内联,因此例如您将无法从 C# 调用它,如果需要,请不要使用函数,使用简单和标准的方法重载。
假设我有两个不同的 library 类型:
type Foo = { foo : string }
type Bar = { bar : int32 }
我想实现适用于 Foo
或 Bar
实例的通用函数 zoo
。 而且我无法更改 Foo
和 Bar
,因为它们是库代码的一部分。
这是我第一次尝试使用类型扩展和内联函数 here:
// Library.fs
module Library
type Foo = { foo : string }
type Bar = { bar : int32 }
// Program.fs
type Foo with
static member zoo (f : Foo) = "foo"
type Bar with
static member zoo (b : Bar) = "bar"
let inline zoo (x : ^t) =
(^t : (static member zoo : ^t -> string) x)
let f = zoo { foo = "1" } // error FS0001: The type 'Foo' does not support the operator 'zoo'
为什么内联函数定义不依赖于类型扩展?如何在不更改初始 Foo
和 Bar
类型定义的情况下解决我的问题?
到目前为止我能得到的最好的东西是
type Ext =
static member zoo (f : Foo) = "foo"
static member zoo (b : Bar) = "bar"
let f = Ext.zoo { foo = "1" } // "foo"
let b = Ext.zoo { bar = 2 } // "bar"
这不是最好的解决方案,也不是很通用,但至少它有效。
使用方法重载。
扩展方法的问题是在 solving member constraints 时没有考虑到扩展方法。
因此您可以使用方法重载,如您自己的答案中所示,或者您可以更进一步,通过使用中间类型和中间方法(在本例中为简单起见,使用运算符)来创建内联泛型函数诀窍:
type T = T with
static member ($) (T, x:Foo) = "foo"
static member ($) (T, x:Bar) = "bar"
let inline zoo x = T $ x
let f = zoo { foo = "1" }
这里有 more details 其工作原理。
请注意,此函数将被内联,因此例如您将无法从 C# 调用它,如果需要,请不要使用函数,使用简单和标准的方法重载。