Ono*_*cci 3 f# interface units-of-measurement mixins
考虑以下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
Run Code Online (Sandbox Code Playgroud)
我想使用这些接口作为对度量类型进行分组的方法,并且作为允许"任何度量"和"特定度量"之间的一般性级别的方式 - 类似于:
(* Yes, I know this syntax is probably incorrect *)
let rate (distance:float<'u:#ILinear,#IMetric>) (time:float<time>) =
distance/time
Run Code Online (Sandbox Code Playgroud)
我意识到这可能会推动可能性的限制,但我只是好奇,如果这是可能的,如果是这样,语法将是什么.正如我所说,这是使用接口作为一个穷人的混合.
我不认为这是可能的,但我非常喜欢这个想法:-).
如果可能,那么约束可能使用相同的语法编写,您可以使用该语法为普通(非度量)类型参数编写接口约束:
let rate<[<Measure>] 'u when 'u :> IMetric> (distance:float<'u>) (time:float<time>) =
distance/time
Run Code Online (Sandbox Code Playgroud)
错误信息清楚地表明约束只能在普通类型参数上指定(实际上,我甚至惊讶于度量单位可以实现接口 - 它看起来并不是非常有用,因为它们在编译期间被完全擦除):
错误FS0703:预期的类型参数,而不是度量单位参数
我能想到的最好的解决方法是编写一个简单的包装器来存储一个值(带有一些单元)和另一个(幻像)类型来表示约束:
[<Struct>]
type FloatValue<[<Measure>] 'u, 'constr>(value:float<'u>) =
member x.Value = value
let cm f = FloatValue<_, IMetric>(f * 1.0<cm>)
Run Code Online (Sandbox Code Playgroud)
该cm函数采用浮动并将其包装成一个FloatValue.第二个类型参数是普通类型参数,因此可以提供一些实现接口的类型(或仅使用单个接口).该rate函数看起来像这样:
let rate (distance:FloatValue<'u, #IMetric>) (time:float<time>) =
distance.Value / time
Run Code Online (Sandbox Code Playgroud)
由于无法在单元类型上指定约束,因此我们必须在第二个类型参数上指定它们.然后您可以使用以下方法调用该函数
rate (cm 10.0) 5.0<time>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
381 次 |
| 最近记录: |