-
Notifications
You must be signed in to change notification settings - Fork 0
/
reverse.hs
149 lines (110 loc) · 2.84 KB
/
reverse.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
{-# LANGUAGE
UnicodeSyntax
#-}
module Main where
import Prelude hiding (iterate, reverse)
import Data.IORef
data LinkedList a
= None
| Node { value ∷ IORef a
, next ∷ IORef (LinkedList a)
}
linkedlist ∷ a → IO (LinkedList a)
linkedlist x =
do
v ← newIORef x
n ← newIORef None
pure $ Node { value = v , next = n }
get_value ∷ LinkedList a → IO a
get_value n =
case n of
None → error "Empty"
node → (readIORef $ value node) >>= \ x → pure x
set_value ∷ a → LinkedList a → IO ()
set_value x n =
case n of
None → pure ()
node → writeIORef (value node) x
get_next ∷ LinkedList a → IO (LinkedList a)
get_next n =
case n of
None → error "Empty"
node → (readIORef $ next node) >>= \x → pure x
set_next ∷ LinkedList a → LinkedList a → IO ()
set_next n1 n2 =
case n1 of
None → pure ()
node → writeIORef (next node) n2
reverse ∷ LinkedList a → IO (LinkedList a)
reverse l =
let reverse' ∷ LinkedList a → LinkedList a → IO (LinkedList a)
reverse' n1 n2 =
case n2 of
None → pure n1
_ → do
n3 ← get_next n2
set_next n2 n1
reverse' n2 n3
in
reverse' None l
iterate ∷ (a → IO ()) -> LinkedList a -> IO ()
iterate f l =
case l of
None → pure ()
_ →
do
v ← get_value l
f v
n ← get_next l
iterate f n
print_list ∷ Show a ⇒ LinkedList a → IO ()
print_list l =
iterate (\ x → putStr $ show x ++ " ") l
main ∷ IO ()
main =
do
l1 ← linkedlist 1
l2 ← linkedlist 2
l3 ← linkedlist 3
l4 ← linkedlist 4
l5 ← linkedlist 5
let lists = [ ("l1", l1) , ("l2", l2) ,
("l3", l3) , ("l4", l4) ,
("l5", l5)
]
putStr "\n"
putStr ">>> Before linking the lists\n"
mapM_ (\ (s, l) →
do
putStr $ s ++ " : "
print_list l
putStr "\n"
)
lists
set_next l1 l2
set_next l2 l3
set_next l3 l4
set_next l4 l5
putStr "\n"
putStr ">>> After linking and before reversing the linked list\n"
mapM_ (\ (s, l) →
do
putStr $ s ++ " : "
print_list l
putStr "\n"
)
lists
putStr "\n"
putStr " The evaluation of `reverse l1´ computes the reversed\n\
\ list of l1 and the final result is equal to l5,\n\
\ the new head of the linked list.\n\n"
_ ← reverse l1
putStr ">>> After reversing the linked list\n"
mapM_ (\ (s, l) →
do
putStr $ s ++ " : "
print_list l
putStr "\n"
)
lists
putStr "\n"