簡體   English   中英

如何在F#中創建一個值類型的聯合類型?

[英]How to create a Union type in F# that is a value type?

普通F#區分聯合是引用類型。 如何在F#中創建一個簡單的 (非遞歸的,只有值類型的字段)聯合類型,它是一個值類型?

根據一些互聯網搜索,我當前(非工作)的嘗試看起來如下:

[<StructLayout(LayoutKind.Explicit)>]
type Float =
    [<DefaultValue>] [<FieldOffset 0>] val mutable Val1 : float
    [<DefaultValue>] [<FieldOffset 0>] val mutable Int1 : int
    new (a:float) = {Val1 = a}    

以下博客文章顯示通過C#顯示可能的內容

我知道上面的內容並不是慣用的F#,但我試圖優化我的應用程序的一部分性能,並且分析清楚地表明堆分配(JIT_new)的成本是導致我的性能瓶頸的原因。簡單的聯合類型是滿足我需求的完美數據結構,而不是堆分配的。

首先,我可能無法做到這一點,除非我有非常好的理由。 在大多數情況下,結構和引用類型之間的區別並不是那么大 - 根據我的經驗,只有當你有一個非常大的數組(然后結構允許你分配一個大的內存塊)時才重要。

也就是說,看起來F#不喜歡你的例子中的構造函數代碼。 我真的不確定為什么(它似乎做了一些檢查對於重疊結構不太有效),但以下是訣竅:

[<Struct; StructLayout(LayoutKind.Explicit)>]
type MyStruct =
    [<DefaultValue; FieldOffset 0>] 
    val mutable Val1 : float
    [<DefaultValue; FieldOffset 0>] 
    val mutable Int1 : int
    static member Int(a:int) = MyStruct(Int1=a)
    static member Float(f:float) = MyStruct(Val1=f)

如果我真的想要使用它,我會添加另一個包含10字段Tag ,具體取決於結構所代表的情況。 然后,您可以使用活動模式對其進行模式匹配,並獲得一些有區別的工會的安全性:

let (|Float|Int|) (s:MyStruct) = 
  if s.Tag = 0 then Float(s.Val1) else Int(s.Int1)

現在,F#支持結構聯合,有關詳細信息,請參閱F#RFC FS-1014 簡而言之:

 // Single case: [<Struct>] type UnionExample = U of int * int * bool // Multi-case: [<Struct>] type Shape = | Circle of radius: double | Square of side: int 

結構記錄的主要區別:

  • 您不能對定義的相同類型進行循環引用。 例如:類型T = U的T
  • 您也無法調用默認的ctor,就像使用普通的F#結構一樣。
  • 對於多案例結構聯合,每個案例必須具有唯一的名稱。

暫無
暫無

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

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