如何将 OO 调用转换为一些通用函数调用
How to transform OO calls into a some generic function calls
我有以下代码
type Show<'a> =
abstract member Show: 'a -> string
type Shows() =
member inline this.GetShow(x:string) =
{new Show<string> with member this.Show(x:string) = x}
member inline this.GetShow(x:int) =
{new Show<int> with member this.Show(x:int) = sprintf "%A" x}
如果我使用普通的 OO 表示法调用它,它会完美运行。
printfn "100 %s" (Shows().GetShow("some").Show("some"))
但是我想把它包装成一个函数,这样
let inline show x = (Shows().GetShow(x).Show(x))
但这给了我以下错误
[FS0041] A unique overload for method 'GetShow' could not be determined based
on type information prior to this program point. A type annotation may be
needed. Candidates:
member Shows.GetShow : x:int -> Show<int>,
member Shows.GetShow : x:string -> Show<string>
有什么办法可以克服这个问题吗?
您必须使用静态解析的类型参数,并明确声明您希望该类型具有具有所需签名的 GetShow
成员。此外,这仅适用于静态成员。
type Shows() =
static member inline GetShow(x:string) =
{new Show<string> with member this.Show(x:string) = x}
static member inline GetShow(x:int) =
{new Show<int> with member this.Show(x:int) = sprintf "%A" x}
let inline ($) (a: ^a) (b: ^b) =
((^a or ^b): (static member GetShow : ^b -> Show< ^b>) b)
let inline show x = (Shows() $ x).Show(x)
将约束包含在单独的运算符 $
中是必要的,因为您只能对类型参数指定静态解析的约束 - 即您不能说 (when Show : (member ...))
之类的东西,不能在那里使用具体类型 Show
,必须是一个参数。所以我们引入一个中间函数$
,然后以Show
为参数调用
我使用运算符 $
而不是常规函数的原因是静态解析的约束是为运算符推断出来的。使用常规函数,您必须编写两次 when ...
子句 - 一次在签名中,一次在正文中。
这是否让您足够接近您想要的?
let inline GetShow p x = (^x : (member GetShow : ^p -> ^o) (x, p))
let inline Show p x = (^x : (member Show : ^p -> ^o) (x, p))
let inline show x s = s |> GetShow x |> Show x
Shows() |> show "a"
Shows() |> show 1
如果在内联函数之外创建 Shows
并不难。这样方法就不需要内联了。
我有以下代码
type Show<'a> =
abstract member Show: 'a -> string
type Shows() =
member inline this.GetShow(x:string) =
{new Show<string> with member this.Show(x:string) = x}
member inline this.GetShow(x:int) =
{new Show<int> with member this.Show(x:int) = sprintf "%A" x}
如果我使用普通的 OO 表示法调用它,它会完美运行。
printfn "100 %s" (Shows().GetShow("some").Show("some"))
但是我想把它包装成一个函数,这样
let inline show x = (Shows().GetShow(x).Show(x))
但这给了我以下错误
[FS0041] A unique overload for method 'GetShow' could not be determined based
on type information prior to this program point. A type annotation may be
needed. Candidates:
member Shows.GetShow : x:int -> Show<int>,
member Shows.GetShow : x:string -> Show<string>
有什么办法可以克服这个问题吗?
您必须使用静态解析的类型参数,并明确声明您希望该类型具有具有所需签名的 GetShow
成员。此外,这仅适用于静态成员。
type Shows() =
static member inline GetShow(x:string) =
{new Show<string> with member this.Show(x:string) = x}
static member inline GetShow(x:int) =
{new Show<int> with member this.Show(x:int) = sprintf "%A" x}
let inline ($) (a: ^a) (b: ^b) =
((^a or ^b): (static member GetShow : ^b -> Show< ^b>) b)
let inline show x = (Shows() $ x).Show(x)
将约束包含在单独的运算符 $
中是必要的,因为您只能对类型参数指定静态解析的约束 - 即您不能说 (when Show : (member ...))
之类的东西,不能在那里使用具体类型 Show
,必须是一个参数。所以我们引入一个中间函数$
,然后以Show
为参数调用
我使用运算符 $
而不是常规函数的原因是静态解析的约束是为运算符推断出来的。使用常规函数,您必须编写两次 when ...
子句 - 一次在签名中,一次在正文中。
这是否让您足够接近您想要的?
let inline GetShow p x = (^x : (member GetShow : ^p -> ^o) (x, p))
let inline Show p x = (^x : (member Show : ^p -> ^o) (x, p))
let inline show x s = s |> GetShow x |> Show x
Shows() |> show "a"
Shows() |> show 1
如果在内联函数之外创建 Shows
并不难。这样方法就不需要内联了。