使用List.sum时类型约束不匹配

f#

我可能已经离开 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 成员 ( + ) 和成员 get_Zero 之类的通用约束有关,但这不可能是整个故事,因为compileslet foo values = List.max valuesList.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。


以上是使用List.sum时类型约束不匹配的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>