将Seq模块操作应用于子类型,同时将原始类型保留在f#中

时间:2012-03-28 15:08:07

标签: generics f# sequence covariance

我想专门化列表类型来表示时间系列。 这将允许一些额外的方法和更好的可读性。

我想重用Seq模块中编写的所有函数,同时保留原始底层类型。

module Analytics =
   open System

   type TimeSerie<'T> () =
      inherit ResizeArray<DateTime*'T> ()


module TimeSerie =
   open Analytics
   let filter f (ts:TimeSerie<'T>) = (Seq.filter f (ts)) |> ResizeArray.ofSeq :?> TimeSerie<'T> 
   .... same for map, etc..

有没有其他方法可以切断代码?

2 个答案:

答案 0 :(得分:2)

简而言之,没有。

没有简单的方法可以做到这一点。这就是为什么ListArraySeq模块有自己的高阶函数实现的原因之一。

在您的示例中,我建议使用ResizeArray module中的F# PowerPack,您可以在其中使用所有高阶函数。 ResizeArray<DateTime*'T>的专业化可以通过将其包装在一个单一案例的歧视联盟中来完成。

答案 1 :(得分:1)

通常,没有办法做你想要的,因为没有标准的方法在F#或.NET中构建't seq的任意子类型。我所知道的唯一的半主流编程语言就像Scala一样,而且Scala集合库非常复杂。

为了说明定义更“通用”Seq.filter函数的一个问题,请考虑以下类型定义:

type Singleton<'t>(t:'t) =
    interface seq<'t> with
        member __.GetEnumerator() : System.Collections.IEnumerator = 
            ([t] :> System.Collections.IEnumerable).GetEnumerator()
        member __.GetEnumerator() : System.Collections.Generic.IEnumerator<'t> = 
            ([t] :> seq<_>).GetEnumerator()

现在,此类的所有实例都只有一个元素,但过滤将导致序列中包含零个或一个元素。显然,这意味着静态类型

Singleton(1)
|> Seq.filter (fun x -> x > 5)

必须是Singleton<int>以外的其他内容。