如何在F#中创建作为值类型的Union类型? [英] How to create a Union type in F# that is a value type?

查看:66
本文介绍了如何在F#中创建作为值类型的Union类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

常规F#区分联合是引用类型.如何在F#中创建一个简单(非递归且仅具有值类型字段)联合类型?

Normal F# Discriminated Unions are reference types. How can I create a simple (non-recursive and with only value-type fields) union type in F# that is a value type?

基于一些互联网搜索,我目前(无效)的尝试如下:

Based on some internet searching my current (non-working) attempt looks as follows:

[<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)是导致性能下降的原因瓶颈...简单的联合类型是满足我需要的理想数据结构,而不仅仅是分配的堆.

I'm aware that the above is NOT idiomatic use of F# but I am trying to optimize the performance of a portion of my application and profiling has clearly shown that the cost of heap allocations (JIT_new) is what is causing my performance bottleneck... A simple union type is the perfect data structure for my needs, just not a heap allocated one.

推荐答案

首先,除非有很好的理由,否则我可能不会这样做.在大多数情况下,结构和引用类型之间的差异实际上并没有那么大-根据我的经验,仅当它们具有非常大的数组时才有意义(然后结构允许您分配一个大的内存块).

First of all, I would probably not do this, unless I had very good reasons. In most cases, the difference between structs and reference types is not really that big - in my experience, it only matters when you have a very large array of them (then structs let you allocate one big memory chunk).

也就是说,看起来F#不喜欢示例中的构造函数代码.我真的不确定为什么(它似乎正在做一些检查,但对于重叠的结构却不太有效),但是以下方法可以解决问题:

That said, it looks like F# does not like the constructor code in your example. I'm really not sure why (it seems to be doing some check that does not quite work for overlapping structs), but the following does the trick:

[<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,具体取决于您的结构所代表的情况.然后,您可以使用主动模式在其上进行模式匹配,并获得一些可区分的并集安全性:

If I actually wanted to use this, I would add another field Tag containing 1 or 0 depending on which case your struct represents. Then you could pattern match on it using an active pattern and get some of the safety of discriminated unions back:

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

这篇关于如何在F#中创建作为值类型的Union类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆