【问题标题】:How can I create a measured record type without a measure in F#如何在 F# 中创建没有度量的度量记录类型
【发布时间】:2018-03-05 06:22:58
【问题描述】:

我在 C# (LibC) 和 F# (LibF) 代码都使用的公共库 (LibRoot) 中定义了一个带有度量单位的记录类型。

然后,我在 F# 库 (LibF) 使用的 C# 库 (LibC) 中编写了一个公共 API。但是任何时候我试图将一个对象传递给这个 API F# 都会抱怨它必须有一个度量单位。

//LibRoot - F#
type Vec2<[Measure] 'u> = {
    X : int
    Y : int
}
//LibC - C#
public static class Funcs
{
    public void DoWork(Vec2 vec) { //no measure needed in C#
        ....
    }
}
//LibF - F#

open LibC
let myVec : Vec2<1> = { X = 123; Y = 456 }
DoWork(myVec) //FS0001

错误 FS0001:类型不匹配。期望 'Vec2' 但给定了 'Vec2' 元组有 0和1的不同长度

我试过了:

  • Vec2&lt;1&gt;:FS0001
  • Vec2&lt;0&gt; : 类型中的文字无效
  • Vec2&lt;()&gt; : 类型中出现意外的 ')'
  • Vec2&lt;_&gt;:FS0001
  • Vec2&lt;unit&gt; :预期的计量单位,而不是类型
  • (Vec2) myVec:没有可用于类型 'Vec2
  • 的构造函数

有人知道以互操作友好的方式构造测量记录类型的方法吗?

【问题讨论】:

  • 可能做不到,编译后计量单位信息基本丢失。

标签: f# interop records units-of-measurement


【解决方案1】:

如评论中所述,度量单位是 F# 独有的功能,在编译的 .NET 代码中没有表示,因此当您使用 C# 中的单位注释类型时,它将显示为没有单位的类型。

编译后的 C# 代码不会包含特殊的 F# 元数据来指示这是一个单元注释类型,因此引用您的 C# 库的 F# 编译器不会将其识别为单元注释类型。可以说,F# 编译器可以更聪明地解决这个问题(因为它可以识别出 Vec2 类型最初来自 F#)。

我认为没有一种安全的方法可以将未测量的Vec2 转换为测量的Vec2&lt;_&gt;,但使用unbox 的不安全转换将在运行时起作用:

let v : LibRoot.Vec2<1> = { LibRoot.Vec2.X = 1; Y = 2 }
LibCs.Funcs.DoWork(unbox v)

我认为没有办法在 F# 代码中明确地引用类型 Vec2(没有度量),但 unbox 可以很好地推断类型。这不是很好,所以如果您经常需要这种转换,最好重新设计您的库,以便 C# 使用没有单位的单独类型。

【讨论】:

    【解决方案2】:

    托马斯的回答是正确的。我会为后代分享我的解决方法。

    我的度量单位是

     [<Measure>] type Absolute
     [<Measure>] type Relative 
    

    我介绍了可转换为Vec2&lt;&gt; 以进行互操作的“具体”记录类型。例如

    type Offset2 = { 
       X : int
       Y : int 
    }
       with 
           static member ofVec (vec : Vec2<Relative>) : Offset2 = { X = vec.X; Y = vec.Y }
           static member toVec (off: Offset2) : Vec2<Relative> = { X = off.X; Y = off.Y }
    

    我将它们转换为 Vec2 以执行数学运算,但将“具体”类型用于公共 API。有额外的类型有点烦人,但它可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-27
      • 2011-04-17
      • 2010-12-26
      • 2016-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多