f#类型成员中的静态解析类型

时间:2012-12-24 18:45:19

标签: f# type-inference

我想在我自己的类中实现IEnumerable<KeyValuePair<DateTime, 'T>>并向该类添加数学运算符,以便运算符可以像'T的任何数值类型一样工作,就像自动添加约束一样。

我只是无法使下面的代码工作。在成员声明中,它既没有“内联”关键字也没有。

另外,如果我定义一个函数

let inline add l r = l + r 

在类型之前使用它而不是添加l.Value + r.Value,它也不起作用。

有人可以告诉我我做错了吗?

可能整个方法都是错误的,并且有另一种方法可以实现相同的目标吗?

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)

1 个答案:

答案 0 :(得分:6)

你的方法对我来说似乎是正确的。 您的代码无法编译的原因是因为F#类型推断推断出类型变量'T的静态约束(编译时),它与类型定义相同。

无法静态解析类型定义的泛型参数(没有“hat”类型),但没有什么能阻止您定义使用这些编译时约束的函数或成员。

只需在静态成员'T定义中将类型变量'U更改为(+),就可以了。

您仍然可以创建一个不支持TimeSeries的类型(+)实例(例如:TimeSeries<obj>),但您将无法使用{{1}对于那些实例,无论如何,如果你这样做,你将在编译时得到一个很好的错误信息。