gpt4 book ai didi

f# - 内联时扩展方法出错

转载 作者:行者123 更新时间:2023-12-03 00:32:02 25 4
gpt4 key购买 nike

我想扩展一些系统类型,然后通过内联使用它们

type System.String with  
member this.foo n = this + "!" + n

type System.Boolean with
member this.foo n = sprintf "%A!%A" this n

现在我调用这些扩展方法

let x = "foo".foo "bar"
let y = true.foo "bar"

这给了我这个

- val x : System.String = "foobar"
- val y : string = "true!"bar""

一切都很好 - 但现在我想将对 .foo 的调用包装到一个内联函数中

let inline foo n v = (^T : (member foo : ^N  -> ^S) v, n)
let z = foo "bar" "baz"

现在我收到编译器错误告诉我

> The type 'string' does not support the operator 'foo':

嗯...确实如此!

有人可以解释一下发生了什么吗?

最佳答案

静态成员约束中不考虑扩展方法(可能与 this 重复),当您想要使用成员约束实现泛型代码并使其也适用于已定义或原始类型时,这是一个普遍问题。

请参阅user voice请求,还有提到的解决方法 hereDon Syme's explanation of why it's complicated to implement it in the F# compiler .

如果您点击那里的链接,您将看到目前的解决方法,它基本上涉及为所有已知类型创建中间类型和重载,以及为扩展创建通用类型。

这是一个非常基本的示例,说明如何解决该问题:

type Foo = Foo with
static member ($) (Foo, this:int) = fun (n:int) -> this + n
static member ($) (Foo, this:string) = fun n -> this + "!" + n
static member ($) (Foo, this:bool) = fun n -> sprintf "%A!%A" this n

let inline foo this n = (Foo $ this) n

//Now you can create your own types with its implementation of ($) Foo.

type MyType() =
static member ($) (Foo, this) =
fun n -> printfn "You called foo on MyType with n = %A" n; MyType()

let x = foo "hello" "world"
let y = foo true "world"
let z = foo (MyType()) "world"

您可以通过为新类型添加显式泛型重载来增强它:

// define the extensions

type System.String with
member this.foo n = this + "!" + n

type System.Boolean with
member this.foo n = sprintf "%A!%A" this n

// Once finished with the extensions put them in a class
// where the first overload should be the generic version.
type Foo = Foo with
static member inline ($) (Foo, this) = fun n -> (^T : (member foo : ^N -> ^S) this, n)
static member ($) (Foo, this:string) = fun n -> this.foo n
static member ($) (Foo, this:bool) = fun n -> this.foo n
// Add other overloads
static member ($) (Foo, this:int) = fun n -> this + n

let inline foo this n = (Foo $ this) n

//later you can define any type with foo
type MyType() =
member this.foo n = printfn "You called foo on MyType with n = %A" n; MyType()

// and everything will work
let x = foo "hello" "world"
let y = foo true "world"
let z = foo (MyType()) "world"

您可以通过手动编写静态约束并使用成员而不是运算符来进一步细化它(请参阅示例 here ),

最终你会得到这样的结果 generic append来自 FsControl 的函数。

关于f# - 内联时扩展方法出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38071645/

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