2012-10-24 24 views
6

什麼是寫你的功能,使他們能夠無縫地處理的最佳方式:在F#中,你如何處理(float seq)和{ts:DateTime; value:float}以通用的方式?

  • 浮法SEQ
  • 一個時間戳系列類型{TS的:日期時間;值:浮子} SEQ,其中的值是在浮稱爲值

我需要特別寫功能,如計算時間序列的平均值/方差/隨機變換,我想只寫1版本的這些功能。

+2

你想對它們執行哪些操作?你的意思是什麼*通用的方式*? 'float'是一個特殊的類型,不是泛型類型。 – pad

+0

@pad:你是對的讓我改寫問題 – BlueTrin

回答

9

只是轉換帶時間戳的序列轉換爲一個float序列是這樣的:

xs 
|> Seq.map (fun x -> x.value) 
+3

如果你只需要用值來計算,那麼這就是要走的路。但顯然,如果您需要考慮時間戳(例如,插入您需要的時間值),它也不起作用。這就是爲什麼我的答案顯示出更復雜的方法。 –

13

正如在評論中提到的那樣,關鍵問題是您想要在數據類型上寫什麼樣的操作。對基本的數值運算可能會這樣做,但如果您需要更復雜的計算,那麼編寫兩個單獨的函數可能會更容易。

無論如何,如果你想使用基本的數值運算,那麼你需要爲你的時間戳類型定義標準的數值運算符。我描述了​​。下面的工具+,除以整數和零:

open System 

type TimedFloat = 
    { Time : DateTime 
    Value : float } 
    static member (+) (tf1, tf2) = 
    { Time = DateTime(tf1.Time.Ticks + tf2.Time.Ticks) 
     Value = tf1.Value + tf2.Value } 
    static member Zero = 
    { Time = DateTime.MinValue 
     Value = 0.0 } 
    static member DivideByInt(tf, n) = 
    { Time = DateTime(tf.Time.Ticks/int64 n) 
     Value = tf.Value/float n } 

+運營商有點懷疑,因爲你有一些非常大的日子結束了(或許用TimeSpan從上會更有意義) 。然而,一旦你定義了運營商,你可以,例如,使用Seq.average

[ { Time = DateTime.Now 
    Value = 3.0 } 
    { Time = DateTime.Now.AddDays(2.0) 
    Value = 10.0 } ] 
|> Seq.average 

,因爲它是使用靜態成員的約束(這意味着它可以在有必要的任何類型寫在這兩種類型的Seq.average功能的工作原理成員)。編寫這樣的函數比編寫普通函數更困難,所以我可能不會默認使用這種風格。無論如何,這是一個introduction with more examples和這個SO answer shows more useful tricks

編輯 -正如喬恩哈羅普指出的,這是相當複雜的方法,它只給你有限的好處。如果您只需要使用,那麼轉換爲值序列是更好的方法。如果你需要更復雜的計算,那麼我認爲不值得編寫一個通用函數。爲float和timestamped值編寫兩個單獨的函數可能會更容易。

+0

感謝您的回答。我一直在想這種事情,因爲我從Haskell來到F#,在那裏我只是尋找一個合適的類型類(或定義我自己的類)來包含多態函數的所有必要類型。如果對這種類型類型沒有好的概念,那麼我會寫兩個函數。我一直忘記F#參與OO世界的概念,比如單個運營商的超載。 –

+0

-1對不起,但看起來像一個真正複雜和低效的替代方案,只是將時間戳序列映射並提取「值」字段,然後將生成的「float seq」提供給您要應用的任何函數。 –

+0

從問題我不能告訴如果OP想要聚合的時間戳以及 - 所以這個答案是sureley沒有錯 - 所以-1是恕我直通員不必要的 - 給你的答案+1 – Carsten