Flaise
Flaise

Reputation: 591

F# type inference less generic than indicated by the type annotations

In the last line of the following code snippet, I get two warnings: This construct causes code to be less generic than indicated by the type annotations. The type variable 'c has been constrained to be type ''a'. and This construct causes code to be less generic than indicated by the type annotations. The type variable 'b has been constrained to be type ''a * 'a'.

type SomeBaseClass<'a> () =
    class end

type SomeClass<'a when 'a:equality> (getValue:unit->'a, ?arg2:SomeBaseClass<'b>) =
    inherit SomeBaseClass<'a*'a>()

    member this.Value with get () = getValue ()

    member this.Transform (transformation:'a->'c) =
        let func ():'c = transformation this.Value
        SomeClass<'c> (func, this) // warnings are attached to this line

This, on the other hand, compiles without issue:

type SomeOtherClass<'a when 'a:equality> (getValue:unit->'a) =
    inherit SomeBaseClass<'a*'a>()

    member this.Value with get () = getValue ()

    member this.Transform (transformation:'a->'c) =
        let func ():'c = transformation this.Value
        SomeOtherClass<'c> func

I don't see anything preventing transformation from returning a different type than it gets passed. I also don't see why that second warning is even a warning because it's obviously already my intention for the 'b type parameter of the new instance to be 'a*'a.

What am I doing wrong here?

Upvotes: 0

Views: 451

Answers (1)

Vandroiy
Vandroiy

Reputation: 6223

The generic type SomeClass is using a generic argument 'b in its constructor that is missing in its definition. Changing the type definition to

type SomeClass<'a, 'b when 'a:equality> ...

and the line with the warning to

    SomeClass(func, this)

removes the error, and the returned class is of type SomeClass<'c, ('a * 'a)>.

I have no idea what this is trying to achieve though, so I can't tell whether this is a sensible correction.

Upvotes: 4

Related Questions