gpt4 book ai didi

generics - 为什么自动泛化有时会推断出过于具体的类型?

转载 作者:行者123 更新时间:2023-12-05 00:53:33 26 4
gpt4 key购买 nike

当运算符的一侧具有已知类型而另一侧没有时,某些函数用法不会编译。一个例子是计量单位:

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

我该怎么办?有什么办法可以说我确实想要更通用的版本?

最佳答案

为了回答您的第一个问题,我认为 F# 编译器不会自动概括泛型类型以包含可能的单位,因此这就是您的第一个示例最终采用 float 的原因。 .如果您在类型注释中指定一个带单位的浮点数,它会被推广到单位上:

let inline multiplyWithFive (x:float<_>) = 5. * x

type [<Measure>] myUnit
multiplyWithFive 3. // Works fine without units
multiplyWithFive 3.<myUnit> // Works fine with units

至于使用支持乘法运算符的任何类型进行此操作 - 我认为 F# 编译器对乘法运算符进行了特殊的封装,以便在您真正只想使用 float 的典型情况下提供合理的默认行为。或 float<_>值。如果您使用显式成员约束定义它,则警告非常清楚:
// warning FS0077: Member constraints with the name 'op_Multiply' 
// are given special status by the F# compiler
let inline amultiplyWithFive (x:^T) : ^R =
(^T : (static member (*) : float * ^T -> ^R) (5.0, x))

// no warning since we're requiring operator **
let inline multiplyWithFive (x:^T) : ^R =
(^T : (static member ( ** ) : float * ^T -> ^R) (5.0, x))

您可能可以通过以更奇特的方式使用静态成员约束来解决此问题 - 有一个 trick that lets you define overloaded operators使用静态 memebrs。但是,我认为这有点扩展了机制,并且可能会对代码的其他部分产生可用性影响。

关于generics - 为什么自动泛化有时会推断出过于具体的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41124948/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com