遅延リストと正格リストを行き来する

結果がインタープリタに表示されなくて残念なことで有名な遅延リストを
任意のタイミングで正格リスト?に変更したり, 逆に正格リストから遅延リストに変換する関数を定義してみました.

fun ! (xs : 'a inflist) : 'a list =
  let
    fun strict nil      = []
      | strict (y:::ys) = y::(strict $ Lazy.force ys)
  in strict xs
  end
fun ? (xs : 'a list) : 'a inflist =
  let
    fun lazy []      = nil
      | lazy (y::ys) = y:::(Lazy.delay (fn ()=>lazy ys))
  in lazy xs
  end

使用例(遅延=>正格)

- range 0 11;
val it = 0 ::: - : int inflist
- ! (range 0 11);
val it = [0,1,2,3,4,5,6,7,8,9,10] : int list

使用例(正格=>遅延)

- curry List.tabulate 10 (fn x=>x);
val it = [0,1,2,3,4,5,6,7,8,9] : int list
- ? (curry List.tabulate 10 (fn x=>x));
val it = 0 ::: - : int inflist

「!」はCleanから持ってきました*1.「?」はなんとなくです.

当然ですが !(fromN 0)*2 とかやると無限ループになります.
ヒープが余ってる人はやってみましょう.

*1:あっちは関数じゃなくて型注釈ですけど

*2:つまり ![0..]