普通 F# 可区分联合是引用类型。我怎样才能创建一个simple(非递归且仅包含值类型字段)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# 可以实现的功能 http://jasonbock.net/Article/UnionsInDotNet
我知道上面的内容不是 F# 的惯用用法,但我正在尝试优化部分应用程序的性能,并且分析清楚地表明堆分配 (JIT_new) 的成本是导致我的性能瓶颈的原因。 . 简单的联合类型是满足我的需要的完美数据结构,只是不是堆分配的类型。
首先,我可能不会这样做,除非我有very很好的理由。在大多数情况下,结构体和引用类型之间的差异并不是那么大 - 根据我的经验,只有当您拥有一个非常大的数组时(然后结构体让您分配一个大的内存块),它才重要。
也就是说,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)
如果我真的想使用这个,我会添加另一个字段Tag
含有1
or 0
取决于您的结构代表的情况。然后,您可以使用活动模式对其进行模式匹配,并恢复受歧视联合的一些安全性:
let (|Float|Int|) (s:MyStruct) =
if s.Tag = 0 then Float(s.Val1) else Int(s.Int1)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)