簡體   English   中英

F#中的類型定義和類型推斷

[英]Type definitions and type inference in F#

我有兩個示例類型,按此順序定義:

type Quote = {QuoteNum: decimal option; ShipToID: decimal option}
type Sales = {SalesNum: decimal option; ShipToID: decimal option}

我正在嘗試編寫一個可以接受兩種類型的函數:

let fx (y: Map<decimal option, _ list>) = 
    y
    |> Map.map (fun key list -> list
                                   |> List.map (fun x -> x.ShipToID))

當我嘗試將Map<decimal option, Quote list>傳遞給函數時,出現錯誤:

Type mismatch. Expecting a
Map<decimal option,Sales list>    
but given a
    Map<decimal option,Quote list>

我原本以為我能夠將兩種類型的映射傳遞給函數,但編譯器似乎推斷只有Map<decimal option, Sales list>才能被函數接受。 我懷疑編譯器最近“看到” Sales類型,並假設這是函數所需要的。 我以為我通過在類型注釋中包含_而使函數相對通用。

如何讓函數接受這兩種類型? 如果不重新定義類型本身,我可以這樣做嗎?

你的懷疑是正確的。 F#需要在那里推斷出單個具體類型,因此將使用它找到的最新匹配類型。

您可以通過使用ShipToID字段定義接口ShipToID兩種類型實現它(不確定是否計算為您重新定義類型),或者通過提供用於提取字段值的getter函數(這將使您保留功能通用):

let fx (shipToIdGetter: 'a -> decimal option) (y: Map<decimal option, 'a list>) = 
    y
    |> Map.map (fun key list -> 
                   list
                   |> List.map (fun x -> shipToIdGetter x))

如果F#支持行多態(如果OCaml恰好是這種情況),您的代碼將按編寫的方式工作。

雖然我相信scrwtp's答案是要走的路,但您也可以選擇使用內聯和成員約束 (或靜態鴨子打字......如果這是一個有效的術語)。 為了完整起見:

type Quote = {QuoteNum: decimal option; ShipToID: decimal option}
type Sales = {SalesNum: decimal option; ShipToID: decimal option}

let inline fx (y: Map<decimal option, 'a list>) = 
    let inline getId x = ( ^a : (member ShipToID : decimal option) x)

    y |> Map.map (fun key list -> list |> List.map getId)


let q : Quote = { QuoteNum = None; ShipToID = None}
let s : Sales = { SalesNum = None; ShipToID = None}

fx <| Map.ofList [ None, [q]]
fx <| Map.ofList [ None, [s]]

getId函數使用相當模糊的語法根據^a的預期結構調用ShipToID成員。

暫無
暫無

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

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