アリスは無限にプラダから猫を取り出す(F#編)

アリスは無限にプラダから猫を取り出す | 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 
カテゴリー: F# パーマリンク