【发布时间】:2021-10-17 22:15:44
【问题描述】:
回复:What is the best way to pass generic function that resolves to multiple types
请先阅读参考链接,然后再继续往下看
我正在尝试扩展这个概念并传递一个通用函数,该函数接受 2 个参数并对其进行处理。
静态方法有效,但是基于接口的方法会导致编译错误(请参阅标有 //error 的代码行):
The declared type parameter '?' cannot be used here since the type parameter cannot be resolved at compile time.
有人知道怎么解决吗?
module MyModule
type T = Content of int
with
static member (+) ((Content i1), (Content i2)) = Content (i1 + i2)
static member (*) ((Content i1), (Content i2)) = Content (i1 * i2)
type W = { Content: int }
with
static member (+) ({Content = i1}, {Content = i2}) = { Content = i1 + i2 }
static member (*) ({Content = i1}, {Content = i2}) = { Content = i1 * i2 }
type Sum = Sum with static member inline ($) (Sum, (x, y)) = x + y
type Mul = Mul with static member inline ($) (Mul, (x, y)) = x * y
let inline f1 (la: 'a list) (lb: 'b list) reducer =
let a = la |> List.reduce (fun x y -> reducer $ (x, y))
let b = lb |> List.reduce (fun x y -> reducer $ (x, y))
(a, b)
type I = abstract member Reduce<'a> : 'a -> 'a -> 'a
let f2 (la: 'a list) (lb: 'b list) (reducer: I) =
let a = la |> List.reduce reducer.Reduce
let b = lb |> List.reduce reducer.Reduce
(a, b)
let main ()=
let lt = [Content 2; Content 4]
let lw = [{ Content = 2 }; { Content = 4 }]
let _ = f1 lt lw Sum
let _ = f1 lt lw Mul
let _ = f2 lt lw { new I with member __.Reduce x y = x + y} //error
let _ = f2 lt lw { new I with member __.Reduce x y = x * y} //error
0
【问题讨论】:
-
问题是,您不能在参数
x和y上使用运算符+或*,因为不知道它们的类型'a是否定义了这些运算符。 -
看来您正面临与泛型类型的经典混淆:选择类型的是泛型函数的调用者,而不是实现者。
-
@FyodorSoikin 在引用的链接中,您提出了接口版本,它比静态版本有优势。你能想出一种方式(不同于我的方式)来使用接口方法获得结果吗?作为替代方案,当这两种方法都可能时,您会采用什么标准在两种方法之间进行选择?
-
我也遇到了这个限制,我认为一般接口方法的问题是你不能使用内联方法,因此所有 F#(非 .Net)静态约束都是无用的。这就是为什么我经常最终使用静态解决方案。