f# Statically resolved types in type members

f#, type-inference

Solution

Your approach seems correct to me. The reason why your code doesn't compile is because F# type inference is inferring a static constraint (compile-time) for the type variable `'T` which is the same used for the type definition.

A generic parameter of a type definition can't be statically resolved (no "hat" types) but nothing stops you from defining a function or a member which uses these compile-time constraints.

Just change your type variable `'T` to `'U` in the static member `(+)` definition and it will be fine.

Still you'll be allowed to create a `TimeSeries` instance of a type which does not support `(+)` (ie: `TimeSeries<obj>`) but you will not be able to use `(+)` for those instances, anyway if you do it you'll get a nice error message at compile-time.

Problem

I want to implement `IEnumerable<KeyValuePair<DateTime, 'T>>` in my own class and add math operators to that class so that the operators could work like inline function on any numeric types of `'T` - automatically add constraints. I just cannot make the following piece of code work. It doesn't work neither with nor without 'inline' keyword at the member declaration. Also, if I define a function ``` let inline add l r = l + r ``` before the type and use it instead of addition l.Value + r.Value, it also doesn't work. Could someone please show me what I am doing wrong? Probably the whole approach is wrong and there is a way to achieve the same goal the other way? ``` namespace Test open System open System.Linq open System.Collections.Generic [<SerializableAttribute>] type TimeSeries<'T>(dictionary : IDictionary<DateTime, 'T>) = let internalList = new SortedList<DateTime, 'T>(dictionary) interface IEnumerable<KeyValuePair<DateTime, 'T>> with member this.GetEnumerator() = internalList.GetEnumerator() member this.GetEnumerator() : Collections.IEnumerator = internalList.GetEnumerator() :> Collections.IEnumerator member private this.sl = internalList static member inline (+) (left : TimeSeries<'T>, right : TimeSeries<'T>) = let res = query { for l in left do join r in right on (l.Key = r.Key) select (l.Key, l.Value + r.Value) } new TimeSeries<'T>(res |> dict) ```

Original source