更新
我发现使用运算符($)
而不是成员的更简单版本。受https://stackoverflow.com/a/7224269/4550898的启发:
type SumOperations = SumOperations
let inline getSum b = SumOperations $ b // <-- puting this here avoids defaulting to int
type SumOperations with
static member inline ($) (SumOperations, x : int ) = x
static member inline ($) (SumOperations, xl : _ list) = xl |> List.sumBy getSum
其余的解释仍然适用,并且很有用。
我找到了一种使之成为可能的方法:
let inline getSum0< ^t, ^a when (^t or ^a) : (static member Sum : ^a -> int)> a : int =
((^t or ^a) : (static member Sum : ^a -> int) a)
type SumOperations =
static member inline Sum( x : float ) = int x
static member inline Sum( x : int ) = x
static member inline Sum(lx : _ list) = lx |> List.sumBy getSum0<SumOperations, _>
let inline getSum x = getSum0<SumOperations, _> x
2 |> getSum |> printfn "%d" // = 2
[ 2 ; 1 ] |> getSum |> printfn "%d" // = 3
[[2; 3] ; [4; 5] ] |> getSum |> printfn "%d" // = 14
运行您的示例:
let list v = List.replicate 6 v
1
|> list |> list |> list |> list |> list
|> list |> list |> list |> list |> list
|> getSum |> printfn "%d" // = 60466176
这是基于将SRTP与成员约束一起使用的:static member Sum
该约束要求类型具有一个称为的成员Sum
,该成员返回int
。使用SRTP时,需要通用功能inline
。
那不是困难的部分。困难的部分是将Sum
成员“添加” 到现有类型,例如int
,List
这是不允许的。但是,我们可以将其添加到新类型SumOperations
中,并将约束始终包含在(^t or ^a)
其中。^t
SumOperations
getSum0
声明Sum
成员约束并调用它。
getSum
SumOperations
作为第一个类型参数 传递给getSum0
static member inline Sum(x : float ) = int x
添加该行是为了说服编译器使用通用动态函数调用,而不仅仅是static member inline Sum(x : int )
调用时的默认值List.sumBy
如您所见,这有点令人费解,语法很复杂,有必要解决编译器上的一些问题,但最终还是可以的。
此方法可以通过添加更多的定义扩展到使用数组,元组,选项等或它们的任何组合工作SumOperations
:
type SumOperations with
static member inline ($) (SumOperations, lx : _ [] ) = lx |> Array.sumBy getSum
static member inline ($) (SumOperations, a : ^a * ^b ) = match a with a, b -> getSum a + getSum b
static member inline ($) (SumOperations, ox : _ option) = ox |> Option.map getSum |> Option.defaultValue 0
(Some 3, [| 2 ; 1 |]) |> getSum |> printfn "%d" // = 6
https://dotnetfiddle.net/03rVWT
getSum (dictList (dictList (..... (dictList dictInt)))) nestedList
,其中的数dictList
匹配的数目[]
中的类型nestedList
。