3

ポイントを定義します

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

そしてシリーズ

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

ここで、このリストのポイントは時間順に並べられていると想定しています。

2 つの時系列を圧縮しようとしています。一般に、それらには同じ時間のポイントがありますが、いずれかのポイントが欠落している可能性があります。

以下のコードで不完全なパターン一致の警告が表示される理由は何ですか?

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
4

2 に答える 2

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

への再帰呼び出しの後に余分な作業がないため、2 つの関数はどちらも末尾再帰loopです。

于 2012-07-06T06:20:01.467 に答える
3

最初のケースでは、コンパイラはガードを確認するだけで、ガードが適用されるか適用されないかを判断するほど賢くありません。これは、最後の where ガードを削除することで修正できます。

2 番目については、末尾再帰であると推測しますが、これらの場合に行う最善の方法は、大きな入力リストを使用してテストし、クラッシュしないかどうかを確認することです。

于 2012-07-06T00:06:16.060 に答える