簡體   English   中英

在F#中輸入和輸出類型參數

[英]Casting to and from a type parameter in F#

我剛剛開始使用F#,而且關於投射的一些問題讓我非常困惑。 不幸的是,我的背景閱讀試圖弄清楚為什么讓我更加困惑,所以我正在尋找一些具體的答案,我可以適應一般的解釋......

我有一個由此函數生成的枚舉的ReadOnlyCollection <'T>:

let GetValues<'T when 'T :> Enum> () =
    (new ReadOnlyCollection<'T>(Enum.GetValues (typeof<'T>) :?> 'T[])) :> IList<'T>

我想要做的是找到其值所使用的枚舉的所有位(即,按位或列表中的所有值),並將其作為通用枚舉類型返回,'T。 這樣做的顯而易見的方法似乎是:

let UsedBits<'T when 'T :> Enum> () =
    GetValues<'T>()
    |> Seq.fold (fun acc a -> acc ||| a) 0

...除了無法編譯之外,錯誤“此處不能使用聲明的類型參數'T',因為在編譯時無法解析類型參數。”

我可以通過首先轉換為Int32來完成實際的工作(我真的不想這樣做,因為我希望這個函數適用於所有枚舉而不管底層類型),即:

let UsedBits<'T when 'T :> Enum> () =
    GetValues<'T>()
    |> Seq.map (fun a -> Convert.ToInt32(a))
    |> Seq.fold (fun acc a -> acc ||| a) 0

...但是然后結果產生為Int32。 如果我嘗試將其強制轉換為'T,我再次遇到編譯錯誤。

我不想在我的問題中過於具體,因為我不確定我應該詢問哪些細節,所以 - 這種方法的缺陷在哪里? 我該怎么辦呢?

(編輯補充: ,@ @ Daniel的回答

唉,這似乎是我不能理解上下文以便理解答案的情況之一,所以...

我理解內聯和不同的約束在你的答案中做了什么,但作為一個F#新手,你是否會介意對這些事情進行一些擴展,以便我可以檢查一下我的理解是不是基於什么? 謝謝。

你可以這樣做:

let GetValues<'T, 'U when 'T : enum<'U>>() = 
  Enum.GetValues(typeof<'T>) :?> 'T[]

let inline GetUsedBits() =
  GetValues() |> Seq.reduce (|||)

inline允許更靈活的約束,即'T (requires member ( ||| )) 沒有它,編譯器必須選擇可以用IL表示的約束,或者,如果不能這樣做,則選擇具體類型。 在這種情況下,它選擇int因為它支持(|||)

這是一個更簡單的復制品:

let Or a b = a ||| b //add 'inline' to compare

有關詳細信息,請參閱MSDN上的靜態已解析的類型參數

暫無
暫無

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

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