UPDATE
ฉันพบรุ่นที่ง่ายกว่าโดยใช้โอเปอเรเตอร์($)
แทนการเป็นสมาชิก แรงบันดาลใจจาก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
นี้จะขึ้นอยู่กับการใช้ SRTPs มีข้อ จำกัด สมาชิก: static member Sum
ข้อ จำกัด ต้องเป็นประเภทที่จะได้เป็นสมาชิกเรียกว่าส่งกลับSum
int
เมื่อใช้ฟังก์ชั่น SRTPs 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