1+ -- 以下のdata型の定義はhttps://www.staff.city.ac.uk/~ross/papers/FingerTree.htmlに記載のあるものを流用している。
2+ data FingerTree a
3+ = Empty -- 要素なし
4+ | Single a -- 要素1つ
5+ | Deep (Digit a ) (FingerTree (Node a )) (Digit a )
6+ deriving (Show )
7+
8+ -- Finger Tree左右端のバッファ
9+ data Digit a
10+ = One a
11+ | Two a a
12+ | Three a a a
13+ | Four a a a a
14+ deriving (Show )
15+
16+ -- Finger Treeの中間圧縮ノード
17+ data Node a
18+ = Node2 a a
19+ | Node3 a a a
20+ deriving (Show )
21+
22+ -- 以降はそれっぽく作っているだけ。
23+
24+ -- 先頭(左端)追加
25+ (<|) :: a -> FingerTree a -> FingerTree a
26+ x <| Empty = Single x
27+ x <| Single a = Deep (One x) Empty (One a)
28+ -- pr: prefix(Digit)
29+ -- m: middle(Node)
30+ -- sf: suffix(Digit)
31+ x <| Deep pr m sf =
32+ case pr of -- 左端のDigitのサイズで分岐
33+ One a -> Deep (Two x a) m sf
34+ Two a b -> Deep (Three x a b) m sf
35+ Three a b c -> Deep (Four x a b c) m sf
36+ Four a b c d -> Deep (Two x a) (Node3 b c d <| m) sf -- TODO
37+
38+ -- 末尾(右端)追加
39+ (|>) :: FingerTree a -> a -> FingerTree a
40+ Empty |> x = Single x
41+ Single a |> x = Deep (One a) Empty (One x)
42+ -- pr: prefix(Digit)
43+ -- m: middle(Node)
44+ -- sf: suffix(Digit)
45+ Deep pr m sf |> x =
46+ case sf of
47+ One a -> Deep pr m (Two a x)
48+ Two a b -> Deep pr m (Three a b x)
49+ Three a b c -> Deep pr m (Four a b c x)
50+ Four a b c d -> Deep pr (m |> Node3 a b c) (Two d x)
51+
52+ data ViewR a
53+ = EmptyR
54+ | FingerTree a :> a
55+ deriving (Show )
56+
57+ -- 末尾(右端)とりだし
58+ viewR :: FingerTree a -> ViewR a
59+ viewR Empty = EmptyR
60+ viewR (Single x) = Empty :> x
61+ viewR (Deep pr m sf) =
62+ case sf of
63+ One a ->
64+ case viewR m of
65+ EmptyR -> digitToTreeR pr
66+ m' :> Node2 b c -> Deep pr m' (Two b c) :> a
67+ m' :> Node3 b c d -> Deep pr m' (Three b c d) :> a
68+ Two a b -> Deep pr m (One a) :> b
69+ Three a b c -> Deep pr m (Two a b) :> c
70+ Four a b c d -> Deep pr m (Three a b c) :> d
71+
72+ digitToTreeR :: Digit a -> ViewR a
73+ digitToTreeR (One a) = Empty :> a
74+ digitToTreeR (Two a b) = Single a :> b
75+ digitToTreeR (Three a b c) = Deep (One a) Empty (One b) :> c
76+ digitToTreeR (Four a b c d) = Deep (Two a b) Empty (One c) :> d
77+
78+ data ViewL a
79+ = EmptyL
80+ | a :< FingerTree a
81+ deriving (Show )
82+
83+ -- 先頭(左端)取り出し
84+ viewL :: FingerTree a -> ViewL a
85+ viewL Empty = EmptyL
86+ viewL (Single x) = x :< Empty
87+ viewL (Deep pr m sf) =
88+ case pr of
89+ One a ->
90+ case viewL m of
91+ EmptyL -> case digitToTree sf of
92+ b :< t -> a :< (b <| t)
93+ Node2 b c :< m' -> a :< Deep (Two b c) m' sf
94+ Node3 b c d :< m' -> a :< Deep (Three b c d) m' sf
95+ Two a b ->
96+ a :< Deep (One b) m sf
97+ Three a b c ->
98+ a :< Deep (Two b c) m sf
99+ Four a b c d ->
100+ a :< Deep (Three b c d) m sf
101+
102+ -- digitをFingerTreeに変換する (ViewL用)
103+ digitToTree :: Digit a -> ViewL a
104+ digitToTree (One a) = a :< Empty
105+ digitToTree (Two a b) = a :< Single b
106+ digitToTree (Three a b c) = a :< Deep (One b) Empty (One c)
107+ digitToTree (Four a b c d) = a :< Deep (Two b c) Empty (One d)
108+
109+ main :: IO ()
110+ main = do
111+ -- 末尾追加
112+ let addFingerTree = scanl (|>) Empty [1 .. 21 ]
113+ putStrLn $ unlines $ map show addFingerTree
114+ putStrLn " --------------------------------------"
115+ -- 先頭追加
116+ let addFingerTree' = scanl (flip (<|) ) Empty $ reverse [1 .. 21 ]
117+ putStrLn $ unlines $ map show addFingerTree'
118+ putStrLn " --------------------------------------"
119+
120+ -- 末端から取り出される過程をみる
121+ let testFingerTree = foldl (|>) Empty [1 .. 21 ]
122+ let removeSteps = scanl (\ ft _ -> restL ft) testFingerTree [1 .. 21 ]
123+ putStrLn $ unlines $ map show removeSteps
124+ putStrLn " --------------------------------------"
125+
126+ -- 先頭から取り出される過程をみる
127+ let testFingerTree = foldl (|>) Empty [1 .. 21 ]
128+ let removeSteps = scanl (\ ft _ -> restL ft) testFingerTree [1 .. 21 ]
129+ putStrLn $ unlines $ map show removeSteps
130+
131+ -- viewRの結果から残りの木を取り出す
132+ restR :: FingerTree a -> FingerTree a
133+ restR ft = case viewR ft of
134+ EmptyR -> Empty
135+ rest :> _ -> rest
136+
137+ -- viewLの結果から残りの木を取り出す
138+ restL :: FingerTree a -> FingerTree a
139+ restL ft = case viewL ft of
140+ EmptyL -> Empty
141+ _ :< rest -> rest
0 commit comments