簡體   English   中英

在F#Array函數中使用區分聯合時如何定義零元素

[英]How to define a zero element when using discriminated unions in F# Array functions

好的,一個問題,我想在Array函數中使用一組有區別的聯合。 在下面的代碼中,我定義了一個類型ResultVari ,它是Unknown或浮點值。 我還為類型定義了infix plus運算符,僅當兩個args都不是Unknown時才返回值。 這很好用。

type ResultVari =
    | Unknown
    | Value of float
    static member (+) (a,b) =   // add two ResultVari's together
        match a,b with
        | Value(av),Value(bv) -> Value(av + bv)  // only has a value if both args do.
        | _ -> Unknown

(* Summation of array of ResultVari, such that if any are unknown then the result is Unknown *)
let example1 = [| Value(4.0); Value(5.5); Value(3.1) |]     // summation should be 12.6
let example2 = [| Value(4.0); Unknown; Value(3.1) |]        // summation should be Unknown

let summation (varArray:ResultVari array) =
    Array.sum (+) varArray       //ERROR this value is not a function and cannot be applied

let summation2 (varArray:ResultVari array) =
    Array.fold (+) (Value(0.0)) varArray       // Works

let sum_example1 = summation2 example1
let sum_example2 = summation2 example2

printfn "%A" sum_example1  // 12.6
printfn "%A" sum_example2  // Unknown

使用summation2 ,程序按預期工作, example1的總和為12.6, example1 example2Unknown

但我不明白為什么summation不起作用 - 編譯器抱怨“這個值不是函數而且不能應用”。 在另一次嘗試(未顯示)中,我也得到了一個缺失的get_Zero元素的錯誤,我理解 - sum函數必須使用某種類型的零定義來開始求和,並使用fold函數和我的值(0.0) )如summation2起始值解決了這個問題。

那么有沒有辦法為有區別的聯合定義get_Zero元素,或者我必須使用記錄類型代替ResultVari? 然后我可以使用Array.sum而不是使用Array.fold。

你需要添加一個zero元素來使用array.sum - 像這樣:

type ResultVari =
    | Unknown
    | Value of float
    static member (+) (a,b) =   // add two ResultVari's together
        match a,b with
        | Value(av),Value(bv) -> Value(av + bv)  // only has a value if both args do.
        | _ -> Unknown
    static member Zero with get() = Value(0.0)

然后代碼變成:

let summation (varArray:ResultVari array) =
    Array.sum varArray

這是有道理的,因為當你總結一些你需要從零開始而沒有零成員時,編譯器不知道從哪里開始。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM