2012-07-05 323 views
2

元組我定義了一個點不完整的模式匹配在F#

type TimeSeriesPoint<'T> = 
    { Time : DateTimeOffset 
     Value : 'T } 

等一系列

type TimeSeries<'T> = TimeSeriesPoint<'T> list 

,我認爲在這個列表中的點按時間排序。

我想壓縮兩個時間序列,其中,一般來說,他們將有同一時間的點,但可能有一些點在其中任何一個缺失。

任何想法爲什麼我在下面的代碼中得到不完整模式匹配的警告?

let zip (series1 : TimeSeries<float>) (series2 : TimeSeries<float>) = 
    let rec loop revAcc ser1 ser2 = 
     match ser1, ser2 with 
     | [], _ | _, [] -> List.rev revAcc 
     | hd1::tl1, hd2::tl2 when hd1.Time = hd2.Time -> 
      loop ({ Time = hd1.Time; Value = (hd1.Value, hd2.Value) }::revAcc) tl1 tl2 
     | hd1::tl1, hd2::tl2 when hd1.Time < hd2.Time -> 
      loop revAcc tl1 ser2 
     | hd1::tl1, hd2::tl2 when hd1.Time > hd2.Time -> 
      loop revAcc ser1 tl2 
    loop [] series1 series2 

如果我這樣寫,我沒有警告,但它是尾遞歸嗎?

let zip' (series1 : TimeSeries<float>) (series2 : TimeSeries<float>) = 
    let rec loop revAcc ser1 ser2 = 
     match ser1, ser2 with 
     | [], _ | _, [] -> List.rev revAcc 
     | hd1::tl1, hd2::tl2 -> 
      if hd1.Time = hd2.Time then 
       loop ({ Time = hd1.Time; Value = (hd1.Value, hd2.Value) }::revAcc) tl1 tl2 
      elif hd1.Time < hd2.Time then 
       loop revAcc tl1 ser2 
      else 
       loop revAcc ser1 tl2 
    loop [] series1 series2 
+0

我會在第一個比賽結束時將它寫成「全部」 _ - > List.rev revAcc – Gustavo 2012-07-06 08:06:10

回答

3

在一般情況下,它是在最後一個模式中有一個反對模式,使其擁有when後衛。

zip,也可以達到同樣的效果zip'確實通過去除多餘的後衛:

let zip (series1: TimeSeries<float>) (series2: TimeSeries<float>) = 
    let rec loop revAcc ser1 ser2 = 
     match ser1, ser2 with 
     | [], _ | _, [] -> List.rev revAcc 
     | hd1::tl1, hd2::tl2 when hd1.Time = hd2.Time -> 
      loop ({ Time = hd1.Time; Value = (hd1.Value, hd2.Value) }::revAcc) tl1 tl2 
     | hd1::tl1, hd2::tl2 when hd1.Time < hd2.Time -> 
      loop revAcc tl1 ser2 
     | hd1::tl1, hd2::tl2 -> 
      loop revAcc ser1 tl2 
    loop [] series1 series2 

兩個兩個函數是尾遞歸,因爲有一個遞歸調用loop後沒有額外的工作。

3

對於第一種情況,編譯器只是看到了警衛,並沒有足夠的智慧來思考時,他們做的/不適用 - 您可以通過刪除最後一個守衛在那裏解決這個問題。

對於第二個我猜想,這是尾遞歸的,但在這些情況下,最好的辦法是用一個大的輸入列表來測試,看看你不死機

+0

使用自定義運算符,可以創建一個類,以便比較返回false,例如'NULL'如何在SQL中工作。 – Guvante 2012-07-27 18:37:27