当运算符的一侧具有已知类型而另一侧没有时,某些函数用法无法编译。一个例子是计量单位:
let inline multiplyWithFive x = 5. * x
type [<Measure>] myUnit
let test = multiplyWithFive 3.<myUnit> // Compiler error
5. * 3.<myUnit>
显然是一个有效的表达式,所以这令人惊讶,特别是考虑到inline
函数在其他情况下最大程度地泛化:
let inline multiply a b = a * b
let test = multiply 5. 3.<myUnit> // Valid
但是,这不仅限于测量单位。比如说,我创建了一个支持非对称乘法和浮点数的类型。它与multiplyWithFive
函数不兼容,它任意推断其参数为float
:
type BoxFloat =
{ Value : float }
static member inline (*) (lhs : float, rhs : BoxFloat) =
{ Value = lhs * rhs.Value }
let boxThree = { Value = 3. }
let test2 = multiplyWithFive boxThree // Compiler error
同样,5. * boxThree
是一个有效的表达式。但自动泛化似乎并未承认这一点。
我可以使用可识别度量单位的类型注释来“修复”第一种情况,但这无缘无故地限制了基础类型。如果我真的需要一个更通用的功能,我不知道如何阻止编译器弥补限制。如果我明确命名一个泛型参数,它只是拒绝保持其泛型:
// Warning: This construct causes code to be less generic than indicated...
let inline multiplyWithFive (x : 'T) = 5. * x
我能做些什么呢?有什么办法可以说我确实想要更通用的版本吗?