如何将OO调用转换为一些通用函数调用

时间:2017-10-17 14:33:57

标签: f# inline

我有以下代码

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>

任何想法如何克服这个?

2 个答案:

答案 0 :(得分:3)

这能让你足够接近你想要的吗?

rdd1 = sc.parallelize([(1,2), (1,9), (2, 3), (3,4)])
df1 = rdd1.toDF(['a', 'b'])
df1 = df1.repartition(3, 'a')
df1.rdd.glom().collect() #outputs like:
>> [[Row(a=2,b=3)], [Row(a=3,b=4)], [Row(a=1,b=2), Row(a=1,b=9)]]

df1.rdd.getNumPartitions()
>>3

rdd2 = sc.parallelize([(1,21), (1,91), (2, 31), (3,41)])
df2 = rdd2.toDF(['a', 'b'])
df2 = df2.repartition(3, 'a')
df2.rdd.glom().collect() #outputs like:
>> [[Row(a=2,b=31)], [Row(a=3,b=41)], [Row(a=1,b=21), Row(a=1,b=91)]]

df2.rdd.getNumPartitions()
>>3


df3 = df1.join(df2, on='a')
df3.rdd.glom().collect() #outputs like:
>> [[Row(a=2,b=3,b=31)], [Row(a=3,b=4,b=41)], [Row(a=1,b=2,b=21), Row(a=1,b=9,b=91)]]
df21.rdd.getNumPartitions()
>>3

如果在内联函数之外创建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 ,那就太难了。这样,方法不需要内联。

答案 1 :(得分:2)

您必须使用静态解析的类型参数,并明确声明您希望该类型具有带有所需签名的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 ...))之类的内容,可以&#39 ; t在那里使用具体类型Show,必须是一个参数。所以我们引入一个中间函数$,然后用Show作为参数调用它。

我使用运算符$而不是常规函数的原因是为运算符推断出静态解析的约束。使用常规函数,您必须两次编写when ...子句 - 一次在签名中,一次在正文中。