-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLinkedList.hs
127 lines (98 loc) · 3.49 KB
/
LinkedList.hs
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
module LinkedList
( LinkedList(..)
, empty
, one
, toLinked
, Tape(..)
, toTape
, toLinkedFromTape
, toTapeFromLinked
, traverseLeft
, traverseRight
) where
-- | LinkedListは双方向連結リストを表す。
data LinkedList a = LNil () () (LinkedList a) -- ^ 左の終端を表す。
| Node (LinkedList a) a (LinkedList a) -- ^ 中間ノードを表す。
| RNil (LinkedList a) () () -- ^ 右の終端を表す。
empty :: LinkedList a
empty = l
where
l = LNil () () r
r = RNil l () ()
one :: a -> LinkedList a
one x = l
where
l = LNil () () n
n = Node l x r
r = RNil n () ()
lNil = LNil () ()
rNil a = RNil a () ()
toLinked :: [a] -> LinkedList a
toLinked = toLinkedFromTape . toTape
data Tape a = TLNil () () [a]
| TNode [a] a [a]
| TRNil [a] () ()
tape :: ([a] -> b) -> ([a] -> a -> [a] -> b) -> ([a] -> b) -> Tape a -> b
tape f g h x = case x of
(TLNil _ _ z) -> f z
(TNode s x z) -> g s x z
(TRNil s _ _) -> h s
tLnil = TLNil () ()
tRNil a = TRNil a () ()
toTape :: [a] -> Tape a
toTape = TLNil () ()
toLinkedFromTape :: Tape a -> LinkedList a
toLinkedFromTape = tape l n r
where
l [] = lNil $ toLinkedFromTape $ tRNil []
l (x:xs) = lNil $ toLinkedFromTape $ TNode [] x xs
n a x b = Node (nl a x b) x (nr a x b)
nl [] x b = toLinkedFromTape $ tLnil $ x:b
nl (a:as) x b = toLinkedFromTape $ TNode as a $ x:b
nr a x [] = toLinkedFromTape $ tRNil $ x:a
nr a x (b:bs) = toLinkedFromTape $ tflip TNode bs b $ x:a
r [] = rNil $ toLinkedFromTape $ tLnil []
r (x:xs) = rNil $ toLinkedFromTape $ TNode xs x []
tflip :: (a -> b -> c -> d) -> c -> b -> a -> d
tflip f x y z = f z y x
toTapeFromLinked :: LinkedList a -> Tape a
toTapeFromLinked (LNil () () a) = TLNil () () (traverseRight a)
toTapeFromLinked (Node a x b) = TNode (traverseLeft a) x (traverseRight b)
toTapeFromLinked (RNil a () ()) = TRNil (traverseLeft a) () ()
traverseLeft :: LinkedList a -> [a]
traverseLeft (LNil () () _) = []
traverseLeft (Node a x _) = x : traverseLeft a
traverseLeft (RNil a () _) = traverseLeft a
traverseRight :: LinkedList a -> [a]
traverseRight (LNil _ () a) = traverseRight a
traverseRight (Node _ x a) = x : traverseRight a
traverseRight (RNil _ () ()) = []
instance (Show a) => Show (Tape a) where
show (TLNil () () a) = "." ++ show a
show (TNode a x b) = show a ++ "[" ++ show x ++ "]" ++ show b
show (TRNil a () ()) = show a ++ "."
instance (Show a) => Show (LinkedList a) where
show = show . toTapeFromLinked
moveLeft :: LinkedList a -> Maybe (LinkedList a)
moveLeft (LNil () () a) = Nothing
moveLeft (Node a x b) = Just a
moveLeft (RNil a () ()) = Just a
moveRight :: LinkedList a -> Maybe (LinkedList a)
moveRight (LNil () () a) = Just a
moveRight (Node a x b) = Just b
moveRight (RNil a () ()) = Nothing
type Trampoline a b = a -> Either b a
toTrampoline :: (a -> Maybe a) -> Trampoline a a
toTrampoline f x = case f x of
Nothing -> Left x
Just a -> Right a
runTrampoline :: Trampoline a b -> a -> b
runTrampoline f x = case f x of
Left b -> b
Right a -> runTrampoline f a
runLoop :: (a -> Maybe a) -> a -> a
runLoop = runTrampoline . toTrampoline
moveToLeftEnd :: LinkedList a -> LinkedList a
moveToLeftEnd = runLoop moveLeft
moveToRightEnd :: LinkedList a -> LinkedList a
moveToRightEnd = runLoop moveRight