Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to understand inferred type constraints

The following yields

This construct causes code to be less generic than indicated by the type annotations. The type variable 'P has been constrained to be type 'bool'.

for the right side of the let myValue = expression, and

This code is less generic than required by its annotations because the explicit type variable 'P' could not be generalized. It was constrained to be 'bool'.

for the generic <'P> in the Value method:

type MyTypeA<'T> (myObject : 'T) as this =
    let myValue = this.Value<bool> "SomeBooleanProperty"

    member this.Value<'P> name = typeof<'T>.GetProperty(name, typeof<'P>).GetValue(myObject, null) :?> 'P`

However, this compiles just fine and yields no warnings or errors:

type MyTypeB<'T> (myObject : 'T) as this =
    member this.Value<'P> name = typeof<'T>.GetProperty(name, typeof<'P>).GetValue(myObject, null) :?> 'P

    member this.Method<'P> name = this.Value<'P> name

What's going on, here? Why, in the first example, is the method recognized in the assignment of the private value, but not as a legitimately generic method?

like image 855
MiloDC Avatar asked Dec 22 '15 05:12

MiloDC


1 Answers

The warning (FS0064) is raised by a call to CheckWarnIfRigid function inside SolveTyparEqualsTyp fun from ConstraintSolver.fs. After the warning is raised, SolveTyparEqualsTyp will continue (since there is no error so far) to solve type constraints. The comment of SolveTyparEqualsTyp is :

/// Add the constraint "ty1 = ty" to the constraint problem, where ty1 is a type variable. 
/// Propagate all effects of adding this constraint, e.g. to solve other variables 

This leads to error FS0663 for member Value definition in OP's example. Followed by error FS0660. For some reason I ignore, some propagation occurs.

Maybe type inference is too aggressively performed. @jpe and other comments below OP's question contain more interesting clues.

like image 106
FZed Avatar answered Nov 06 '22 09:11

FZed