使用 List.sum 时类型约束不匹配
Type constraint mismatch when using List.sum
我可能已经离开 F# 太久了,但我希望它能编译:
module Calc
let foo values = List.sum values
相反,我得到一个编译错误:
FS0071 Type constraint mismatch when applying the default type 'obj' for a type
inference variable. The type 'obj' does not support the operator '+' Consider
adding further type constraints
这也发生在 List.average
上,所以起初我认为它与通用约束有关,例如 requires member ( + ) 和 member get_Zero,但这不是全部,因为 let foo values = List.max values
编译(List.max
也有一个通用约束,尽管更简单 - 它只需要比较)。
我做错了什么?
这是一个 .NET 5.0 项目。在 Visual Studio 和 dotnet build
.
中编译均失败
List.sum
有一个 SRTP 类型,要求列表的元素在其上定义了一个 (+)
运算符:
val sum:
list: list< ^T>
-> ^T (requires static member ( + ) and static member Zero )
当您在不知道列表元素类型的情况下尝试调用它时,编译器无法解析 SRTP。
一个选择 是标记 foo
本身 inline
:
let inline foo values = List.sum values
这样,foo
本身将继承SRTP要求:
val foo:
values: list< ^a>
-> ^a (requires static member ( + ) and static member Zero )
你只是把问题解决了 - 大概到了你知道元素类型的地步。
如果没有 inline
修饰符,这将不起作用,因为 SRTP 无法编译为 IL。
另一个选项,如果你负担得起的话,是指定一个元素类型,这样它就有一个(+)
运算符:
let foo (values: int list) = List.sum values
这样编译器就可以通过观察 int
确实有一个 (+)
运算符来解析 SRTP。
这适用于 List.max
,因为 max
没有 SRTP 约束。它只有一个 'T :> IComparison
约束,由 IL 支持,因此它们不必是 SRTP。
我可能已经离开 F# 太久了,但我希望它能编译:
module Calc
let foo values = List.sum values
相反,我得到一个编译错误:
FS0071 Type constraint mismatch when applying the default type 'obj' for a type inference variable. The type 'obj' does not support the operator '+' Consider adding further type constraints
这也发生在 List.average
上,所以起初我认为它与通用约束有关,例如 requires member ( + ) 和 member get_Zero,但这不是全部,因为 let foo values = List.max values
编译(List.max
也有一个通用约束,尽管更简单 - 它只需要比较)。
我做错了什么?
这是一个 .NET 5.0 项目。在 Visual Studio 和 dotnet build
.
List.sum
有一个 SRTP 类型,要求列表的元素在其上定义了一个 (+)
运算符:
val sum:
list: list< ^T>
-> ^T (requires static member ( + ) and static member Zero )
当您在不知道列表元素类型的情况下尝试调用它时,编译器无法解析 SRTP。
一个选择 是标记 foo
本身 inline
:
let inline foo values = List.sum values
这样,foo
本身将继承SRTP要求:
val foo:
values: list< ^a>
-> ^a (requires static member ( + ) and static member Zero )
你只是把问题解决了 - 大概到了你知道元素类型的地步。
如果没有 inline
修饰符,这将不起作用,因为 SRTP 无法编译为 IL。
另一个选项,如果你负担得起的话,是指定一个元素类型,这样它就有一个(+)
运算符:
let foo (values: int list) = List.sum values
这样编译器就可以通过观察 int
确实有一个 (+)
运算符来解析 SRTP。
这适用于 List.max
,因为 max
没有 SRTP 约束。它只有一个 'T :> IComparison
约束,由 IL 支持,因此它们不必是 SRTP。