Simple and Efficient Purely Functional Queues and Dequesを読む

(ここ数日、眠れない。)

を読んだ。FIFOのキューをリスト二つで実装するというもの。普通のリストでのからlazyリストでのやり方へ。

new = ([], [])

insert e (l, r) = (l, e:r)

remove ([], r) = remove (reverse r, [])
remove (e:l, r) = (e, (l, r))

問題はremove時、reverseのあるなしで時間が変わること。そこでバランスをとるようにしたのが、次のバージョン。

new = ([],[])

insert e (l, r) = makeq (l, e:r)

remove (e:l, r) = (e, makeq (l, r))

makeq (l, r) = if (length r) == (length l) + 1 then
                   (rot (l, r, []), [])
               else
                   (l, r)

rot ([], e:r, a) = e:a
rot (hl:tl, hr:tr, a) = hl:(rot (tl, tr, hr:a))

insert時にlとrの大きさが同じくらいになったとき、lに遅延リストrotとしてまとめている。

その次のは遅延リスト中の各要素の確定を各操作で行う、つまりmakeqのたびに遅延リストrotの1要素をeagerするような実装。3つ目のL'は各makeqでtailしていくためだけにあり、空になったら新たにrotでLをつくりなおし、L'にも入れている。

最後のはそれを前後から挿入削除するのに対応させた実装。