[英]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.