I'm looking to make a function that handles a seq of any numeric type of data (int, float, double), does a little computation on it via mapping, then does a summation of these calculated values. The problem I am running into is that Seq.sum (or really just '(+)' in general) causes the type parameters to be integer, or just give a flat out error. It seems there there should be a way to make this work by using type constraints but I can't seem to get it.
type ValueWithComputation<'v> = {Value: seq<'v>; Computation: 'v -> 'v}
let calculateAndCombine (x: ValueWithComputation<'v>) =
x.Value
|> Seq.map x.Computation
|> Seq.sum // sometimes gives error: "Could not resolve the ambiguity inherent in the use of operator '(+)'
let x = {Value= {1..10}; Computation= (fun x->x*2)}
let y = {Value= {(1.0)..(10.0)}; Computation= (fun x->x*x)}
let totalX = calculateAndCombine x //this causes the code force 'v to be int
let totalY = calculateAndCombine y //gives an error since this isn't an int
This seems similar to F# generics / function overloading syntax but it didn't really explain how to get it to work for all value types.
I got it to work like this. Read the answer linked by Foggy Finder. Then you need additionally the static member Zero
for the sum
to work.
type ValueWithComputation< ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member Zero: ^T)> =
{ Value: seq< ^T>
Computation: ^T -> ^T }
let inline calculateAndCombine x =
x.Value
|> Seq.map x.Computation
|> Seq.sum
let x = {Value= {1..10}; Computation= (fun x->x*2)}
let y = {Value= {(1.0)..(10.0)}; Computation= (fun x->x*x)}
let totalX = calculateAndCombine x
let totalY = calculateAndCombine y