Error messages on functions with generic type constraints can be quite misleading, especially when the solution is to mark a function as inline. Three different (but related) cases of poor messages are shown below:
Example 1
let averageBy (f : 'T -> ^U) (source : seq<'T>) : ^U =
let inline acc (sum, count) el = (Checked.(+) sum (f el), count + 1)
let (sum, count) = Seq.fold acc ((LanguagePrimitives.GenericZero< (^U) >), 0) source
LanguagePrimitives.DivideByInt sum count
Expected behavior
Compiler warning: Checked.(+) is inferred to have default type of int rather than ^U because averageBy is not marked as inline.
Actual behavior
Compiler error on Checked.(+):
Type constraint mismatch when applying the default type 'int' for a type inference variable. The type 'int' does not support the operator 'DivideByInt' Consider adding further type constraints.
Example 2
let averageBy (f : 'T -> ^U) (source : seq<'T>) : ^U =
let acc (sum, count) el = (Checked.(+) sum (f el), count + 1)
let (sum, count) = Seq.fold acc ((LanguagePrimitives.GenericZero< (^U) >), 0) source
LanguagePrimitives.DivideByInt sum count
Expected behavior
Compiler warning: Checked.(+) is inferred to have default type of int rather than ^U because averageBy and/or accare not marked as inline
Actual behavior
Compiler infers type ^U as obj without warnings or errors.
Example 3
let averageBy (f : 'T -> ^U) (source : seq<'T>) : ^U =
let inline acc (sum, count) el = (Checked.(+) sum (f el), count + 1)
let (sum, count) = Seq.fold acc ((LanguagePrimitives.GenericZero< (^U) >), 0) source
Unchecked.defaultof<_> // TODO: finish implementation
Expected behavior
Compiler warning: Checked.(+) is inferred to have default type of int rather than ^U because averageBy and is not marked as inline
Actual behavior
Compiler warning on Checked.(+):
This construct causes code to be less generic than indicated by the type annotations. The type variable 'U has been constrained to be type 'int'.
Error messages on functions with generic type constraints can be quite misleading, especially when the solution is to mark a function as inline. Three different (but related) cases of poor messages are shown below:
Example 1
Expected behavior
Compiler warning:
Checked.(+)is inferred to have default type ofintrather than^UbecauseaverageByis not marked as inline.Actual behavior
Compiler error on
Checked.(+):Example 2
Expected behavior
Compiler warning:
Checked.(+)is inferred to have default type ofintrather than^UbecauseaverageByand/oraccare not marked as inlineActual behavior
Compiler infers type
^Uasobjwithout warnings or errors.Example 3
Expected behavior
Compiler warning:
Checked.(+)is inferred to have default type ofintrather than^UbecauseaverageByand is not marked as inlineActual behavior
Compiler warning on
Checked.(+):