アリスは無限にプラダから猫を取り出す | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/8179
これをF#版に直してみる。
実は、GetCatsメソッドを末尾呼び出しにして、F#のほうは無限に猫を取り出せる…という風にやろうと思ったのだが、この方式だと lst に詰め込むときにスタックオーバーフローになってしまう。
最初は head::tail 方式で書いていたのだが、なんか面倒になって(ツリー構造だから)、外部で list を持っているのが問題かも。
type IObject() = do () type Cat(name) = inherit IObject() member val Name:string = name with get, set type Bag() = inherit IObject() member val Items:IObject list = [] with get, set member x.Add(items) = for it in items do x.Items <- it :: x.Items x // 猫だけ取り出す member x.GetCats() = let rec cats (bag:Bag) = let mutable lst = [] for it in bag.Items do if it.GetType() = typeof<Cat> then lst <- it :: lst else let bag = it :?> Bag lst <- lst @ cats bag lst cats x // main // 入れ子のバッグ let prada = Bag().Add( [Cat("mike"); Bag().Add( [Cat("hop"); Cat("stop"); Cat("jump")]); Cat("kuro"); Cat("shiro")] ) // 猫のみ取り出す for it in prada.GetCats() do let cat = it :?> Cat printfn "cat: %s " cat.Name // 無限バッグを作る let mutable infbag = Bag().Add([Cat("Cheshire")]) infbag.Add([infbag]) |> ignore // 無限に取り出す...ことはできない for it in infbag.GetCats() do let cat = it :?> Cat printfn "cat: %s " cat.Name