Konst Sh
Konst Sh

Reputation: 158

Getting error FS0192: internal error: unexpected non-generation of witness when executing class definition in interactive

I have a class with minimal reproducible implementation looking like that:

type Piecewise<'U, 'V when 'U: comparison
    and 'V : (static member (+): 'V * 'V -> 'V)
    and 'V : (static member (*): 'V * 'V -> 'V)>
    ([<System.ParamArray>] pwArr: ('U * 'U * 'V) array) = 

    member inline this.definition = pwArr

    static member inline map (mapping: 'V -> 'W) (pw: Piecewise2<'U, 'V>) =
        pw.definition
        |> Array.map (fun (b1, b2, v) -> b1, b2, mapping v )
        |> fun x -> Piecewise x

and map member definition causes the error mentioned above when I try to commit this to F# interactive. This class overloads (+) and (*) operators in dowstream members so I had to include them in type constraints. If I set a weaker contraints on types for map member like that:

static member inline map (mapping: _ -> _) (pw: Piecewise<_, _>) = ...

it commits well up to map member but I'm having errors on overloads of (+) operator:

static member inline (+) (pw: Piecewise<'U, 'V>, u: 'V)  =
    Piecewise.map ((+) u) pw
//Polynom.fsx(120,28): warning FS0193: A type parameter is missing a constraint 'when ( ^V or  ^?17597) : (static member (+) :  ^V *  ^?17597 ->  ^?17598)'
//Polynom.fsx(120,9): 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

I'm using F# 6.0 in VS 17.05 on Win 10

Upvotes: 4

Views: 110

Answers (1)

Konst Sh
Konst Sh

Reputation: 158

When I calculate the value for definition field in the let binding first and then assign it to the field the class executes well:

type Piecewise<'U, 'V when 'U: comparison
and 'V : (static member (+): 'V * 'V -> 'V)
and 'V : (static member (*): 'V * 'V -> 'V)>
([<System.ParamArray>] pwArr: ('U * 'U * 'V) array) = 

let definition' =
    pwArr
    |> Array.map (fun (b1, b2, v) ->
        if b1 > b2 then b2, b1, v else b1, b2, v )
    |> Array.sortBy (fun (b1, _, _) -> b1)

member inline this.definition = 
    definition'

member inline this.Evaluate(u: 'U) = 
    this.definition
    |> Array.choose(fun (b1, b2, v) -> 
        if b1 <= u && u < b2 then Some v else None
    )

static member inline map (mapping: 'V -> 'W) (pw: Piecewise<'U, 'V>) =
    pw.definition
    |> Array.map (fun (b1, b2, v) -> b1, b2, mapping v )
    |> fun x -> Piecewise x

Still don't really understanding why this works while the direct assignment doesn't

Upvotes: 2

Related Questions