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

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