Применять операции модуля Seq к подтипу, сохраняя оригинальный тип в f # - PullRequest
1 голос
/ 28 марта 2012

Я хочу специализировать тип списка для представления временной серии. Это позволит использовать некоторые дополнительные методы и улучшить удобочитаемость.

Я хотел бы повторно использовать все функции, написанные в модуле 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 ]

2 голосов
/ 28 марта 2012

Короче, нет.

Нет простого способа сделать это.Это одна из причин, почему модули List, Array и Seq имеют свои собственные реализации этих функций высокого порядка.

В вашем примере я предлагаю использовать модуль ResizeArray из F # PowerPack , где у вас есть все функции высокого порядка, готовые к использованию.Специализация на ResizeArray<DateTime*'T> может быть осуществлена ​​путем объединения его в единичные дискриминационные союзы.

1 голос
/ 28 марта 2012

В общем, нет способа сделать то, что вы хотите, так как нет стандартного способа создания произвольных подтипов 't seq в F # или .NET. Единственный полу-мейнстримовый язык программирования, который мне известен, который делает что-то похожее на то, что вы ищете, это 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>.

...