interface - 测量单位、接口(interface)和 Mixin

标签 interface f# mixins units-of-measurement

考虑以下 F# 代码:

type ILinear =
  interface 
  end

type IMetric =
  interface
  end


[<Measure>] type cm =
    interface ILinear
    interface IMetric 

[<Measure>] type m =
    interface ILinear
    interface IMetric

[<Measure>] type time

我想使用这些接口(interface)作为对度量类型进行分组的方法,并作为允许“任何度量”和“特定度量”之间一定程度的通用性的方法——类似于:

(* Yes, I know this syntax is probably incorrect *)    
let rate (distance:float<'u:#ILinear,#IMetric>) (time:float<time>) =
       distance/time

我意识到这可能会突破可能性的极限,但我只是有点好奇这是否可能,如果可能的话,语法会是什么。正如我所说,这是使用接口(interface)作为穷人的混合。

最佳答案

我认为这是不可能的,但我很喜欢这个想法:-)。

如果可能的话,那么约束可能会使用与为普通(非测量)类型参数编写接口(interface)约束相同的语法来编写:

let rate<[<Measure>] 'u when 'u :> IMetric> (distance:float<'u>) (time:float<time>) =
    distance/time

错误消息清楚地表明约束只能在普通类型参数上指定(实际上,我什至感到惊讶的是度量单位可以实现接口(interface) - 它看起来不太有用,因为它们在编译过程中被完全删除):

error FS0703: Expected type parameter, not unit-of-measure parameter

我能想到的最好的解决方法是编写一个简单的包装器来存储一个值(带有一些单位)和表示约束的附加(幻像)类型:

[<Struct>]    
type FloatValue<[<Measure>] 'u, 'constr>(value:float<'u>) =
  member x.Value = value

let cm f = FloatValue<_, IMetric>(f * 1.0<cm>)

cm 函数接受一个 float 并将其包装到 FloatValue 中。第二个类型参数是普通类型参数,因此可以为它提供某种实现接口(interface)的类型(或仅提供单个接口(interface))。 rate 函数如下所示:

let rate (distance:FloatValue<'u, #IMetric>) (time:float<time>) =
  distance.Value / time

由于无法在单元类型上指定约束,因此我们必须在第二个类型参数上指定它们。然后您可以使用以下方式调用该函数:

rate (cm 10.0) 5.0<time>

关于interface - 测量单位、接口(interface)和 Mixin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6920673/

相关文章:

go - 具有接口(interface)类型和结构指针的 channel 作为具体类型

sql-server-2008 - 在 F# 中,如何使用 Type Provider 访问 Sql Server Geography 数据类型?

f# - 将 Pipe Forward 与嵌套序列一起使用

f# - 是否可以使用序列尾部调用优化 f# 中的分组函数?

Ruby:在类方法中使用模块方法

java - 如果同名字段继承自两个源(类和接口(interface))会发生什么

Android 接口(interface)和 onCreate()

css - 为什么在 SASS 中 #{$var} 之后没有编译括号?

c# - 在 List<MyType> 和 List<IMyType> 之间进行转换

javascript - 验证提供的值是否是 Lodash 的实例