アリスは無限にプラダから猫を取り出す | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/8179
これをF#版に直してみる。
実は、GetCatsメソッドを末尾呼び出しにして、F#のほうは無限に猫を取り出せる…という風にやろうと思ったのだが、この方式だと lst に詰め込むときにスタックオーバーフローになってしまう。
最初は head::tail 方式で書いていたのだが、なんか面倒になって(ツリー構造だから)、外部で list を持っているのが問題かも。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 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 |