[英]Issue with generically casting a float with units to different units in F#
I am having a major issue handling units of measure in F#.我在处理 F# 中的测量单位时遇到了一个重大问题。 I have handled them successfully so far, but I have only either been removing units to get back a
float
or casting a float
to one with units.到目前为止,我已经成功地处理了它们,但我只是要么移除单元以取回
float
,要么将float
转换为带有单元的浮点数。 However, now I have a use case where I need to generically drop units off of a float and give them new units.但是,现在我有一个用例,我通常需要从浮点数中删除单位并给他们新的单位。 At present, I see no way that this is possible in F#.
目前,我认为这在 F# 中是不可能的。
For example:例如:
> let removeUnits (x: float<'Unit>) = float x;;
val removeUnits: x: float<'Unit> -> float
> let castUnits<[<Measure>] 'Unit> (x: float) = LanguagePrimitives.FloatWithMeasure<'Unit> x;;
val castUnits: x: float -> float<'Unit>
> let convertUnits<[<Measure>] 'NewUnit> (x: float<'OldUnit>) : float<'NewUnit> =
x |> removeUnits |> castUnits<'NewUnit>;;
let convertUnits<[<Measure>] 'NewUnit> (x: float<'OldUnit>) : float<'NewUnit> =
-------------------------------------------------^^^^^^^^
stdin(8,47): warning FS0064: This construct causes code to be less generic than indicated by the type annotations. The unit-of-measure variable 'OldUnit has been constrained to be measure '1'.
val convertUnits: x: float -> float<'NewUnit>
This almost seems like a bug to me.这对我来说几乎像是一个错误。 The types of the pipeline should be
float<'OldUnit> -> float -> float<'NewUnit>
, because those are the type signatures of the component functions.管道的类型应该是
float<'OldUnit> -> float -> float<'NewUnit>
,因为这些是组件函数的类型签名。 I'm not understanding why out of nowhere that 'OldUnit
is being constrainted to 1
.我不明白为什么
'OldUnit
被限制为1
。
How can I do this properly?我怎样才能正确地做到这一点? I want a function with signature
val convertUnits: x: float<'OldUnit> -> float<'NewUnit>
, where the function only changes the units and leaves the underlying float values alone.我想要一个带有签名
val convertUnits: x: float<'OldUnit> -> float<'NewUnit>
,其中 function 仅更改单位并单独保留基础浮点值。
Is this a bug in the compiler?这是编译器中的错误吗?
That's just because you explicitly gave your function only one type parameter - 'NewUnit
, - but in its signature you're using two - 'OldUnit
and 'NewUnit
.那只是因为你明确地给你的 function 一个类型参数 -
'NewUnit
,但在它的签名中你使用了两个 - 'OldUnit
和'NewUnit
。
Give the function both parameters like this:给 function 两个参数,如下所示:
let convertUnits<[<Measure>] 'NewUnit, [<Measure>] 'OldUnit> (x: float<'OldUnit>) : float<'NewUnit> =
x |> removeUnits |> castUnits<'NewUnit>
Or, alternatively, let the compiler infer them by itself:或者,或者,让编译器自己推断它们:
let convertUnits (x: float<'OldUnit>) : float<'NewUnit> =
x |> removeUnits |> castUnits<'NewUnit>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.