Type resolution reports FS0001 and FS0043 with the same error, that a constraint is required - but that constraint is already specified
Crazy code sample:
type Tuple =
static member inline TupleMap ((a, b), _ : Tuple) = fun f -> (f a, f b)
static member inline TupleMap ((a, b, c), _ : Tuple) = fun f -> (f a, f b, f c)
static member inline TupleMap ((a, b, c, d), _ : Tuple) = fun f -> (f a, f b, f c, f d)
static member inline Map f (x: 'Tin) : 'Tout =
let inline call_2 (a: ^a, b : ^b) = ((^a or ^b) : (static member TupleMap : ^b * _ -> ^t) (b, a))
call_2 (Unchecked.defaultof<Tuple>, x) f
type IOption<'T> =
abstract member Value : 'T
module Something =
let inline tupleMap f x = Tuple.Map f x
let inline addOptionValues< ^value, ^options, ^values, 'item when
'item :> IOption< ^value>
and (Tuple or ^options) : (static member TupleMap : ^options * Tuple -> ('item -> ^value) -> ^values)>
(addUp : ^values -> ^value, sourceOptions : ^options) =
let getValue (i : 'item) = i.Value
let allValues : ^values = tupleMap getValue sourceOptions
let result : ^value = addUp allValues
result
The line
let allValues : ^values = tupleMap getValue sourceOptions
Gives the errors
Error FS0043 A type parameter is missing a constraint 'when (Tuple or ^options) : (static member TupleMap : ^options * Tuple -> ('item -> ^value) -> ^values)'
Error FS0001 A type parameter is missing a constraint 'when (Tuple or ^options) : (static member TupleMap : ^options * Tuple -> ('item -> ^value) -> ^values)'
Provide any related information
Hi @marklam,
I believe this is the same issue as #4924 (which you may want to read for background information). This should make your code work:
type Tuple =
static member inline TupleMap ((a, b), _ : Tuple) = fun f -> (f a, f b)
static member inline TupleMap ((a, b, c), _ : Tuple) = fun f -> (f a, f b, f c)
static member inline TupleMap ((a, b, c, d), _ : Tuple) = fun f -> (f a, f b, f c, f d)
static member inline Map f (x: 'Tin) : 'Tout =
let inline call_2 (a: ^a, b : ^b) = ((^a or ^b) : (static member TupleMap : ^b * _ -> ^t) (b, a))
call_2 (Unchecked.defaultof<Tuple>, x) f
type IOption<'T> =
abstract member Value : 'T
module Something =
let inline tupleMap f x = Tuple.Map f x
let inline addOptionValues (addUp : ^values -> ^value, sourceOptions : ^options) =
let getValue (i : #IOption<_>) = i.Value
// or instead possibly
(* let getValue (i : #IOption< ^value>) = i.Value *)
let allValues : ^values = tupleMap getValue sourceOptions
let result : ^value = addUp allValues
result
Thanks!
@dsyme This is a smaller repro than #4924, but does surface as a different issue. I won't close this as a dupe because of that, but I'll leave that call to you
@marklam the correct solution for your code is:
type Tuple =
static member inline TupleMap ((a, b), _ : Tuple) = fun f -> (f a, f b)
static member inline TupleMap ((a, b, c), _ : Tuple) = fun f -> (f a, f b, f c)
static member inline TupleMap ((a, b, c, d), _ : Tuple) = fun f -> (f a, f b, f c, f d)
static member inline Map f (x: 'Tin) : 'Tout =
let inline call_2 (a: ^a, b : ^b) = ((^a or ^b) : (static member TupleMap : ^b * _ -> ^t) (b, a))
call_2 (Unchecked.defaultof<Tuple>, x) f
type IOption<'T> =
abstract member Value : 'T
module Something =
let inline tupleMap f x = Tuple.Map f x
let inline addOptionValues< ^value, ^options, ^values, 'item when
'item :> IOption< ^value>
and (Tuple or ^options) : (static member TupleMap : ^options * Tuple -> (('item -> ^value) -> ^values))>
(addUp : ^values -> ^value, sourceOptions : ^options) =
let getValue (i : 'item) = i.Value
let allValues : ^values = tupleMap getValue sourceOptions
let result : ^value = addUp allValues
result
The compiler is definitely printing the constraint wrongly although only slightly.
cc @cartermp can you rename the bug report?
Makes sense now I can see it :-)
yeah that was a tricky one but the compiler is very right about complaining :-)
Most helpful comment
Hi @marklam,
I believe this is the same issue as #4924 (which you may want to read for background information). This should make your code work: