Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type constraint mismatch when using List.sum

I may have been away from F# for too long, but I would have expected this to compile:

module Calc

let foo values = List.sum values

Instead, I get a compilation error:

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

This also happens for List.average, so at first I thought it had something to do with generic constraints like requires member ( + ) and member get_Zero, but that can't be the whole story, since let foo values = List.max values compiles (List.max also has a generic constraint, albeit a simpler one - it only requires comparison).

What am I doing wrong?

This is a .NET 5.0 project. Compilation fails both in Visual Studio and with dotnet build.

like image 797
Mark Seemann Avatar asked Nov 18 '25 05:11

Mark Seemann


1 Answers

List.sum has an SRTP type with a requirement that the element of the list has a (+) operator defined on it:

val sum:
   list: list< ^T>
      -> ^T (requires static member ( + ) and static member Zero )

When you try to call that without knowing the type of the list element, the compiler can't resolve the SRTP.


One option would be to mark foo itself inline:

let inline foo values = List.sum values

That way, foo itself will inherit the SRTP requirement:

val foo:
   values: list< ^a>
        -> ^a (requires static member ( + ) and static member Zero )

And you're just kicking the problem down the line - presumably to the point where you know the type of the element.

This doesn't work without an inline modifier, because SRTPs can't be compiled to IL.


Another option, if you can afford it, is to specify an element type, such that it has a (+) operator:

let foo (values: int list) = List.sum values

This way the compiler can resolve SRTP right there by observing that int does indeed have a (+) operator.


This works fine with List.max, because max doesn't have an SRTP constraint on it. It only has an 'T :> IComparison constraint, which are supported by the IL, so they don't have to be SRTP.

like image 121
Fyodor Soikin Avatar answered Nov 21 '25 09:11

Fyodor Soikin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!