Reputation: 158
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
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