comparison doc/intro.ur @ 1500:483cc0602565

Finish tutorial section about common ML/Haskell features
author Adam Chlipala <adam@chlipala.net>
date Fri, 15 Jul 2011 19:21:09 -0400
parents 92c929793d0f
children 841b08995259
comparison
equal deleted inserted replaced
1499:92c929793d0f 1500:483cc0602565
1 (* Introduction *) 1 (* Chapter 1: Introduction *)
2 2
3 (* begin hide *) 3 (* begin hide *)
4 val show_string = mkShow (fn s => "\"" ^ s ^ "\"") 4 val show_string = mkShow (fn s => "\"" ^ s ^ "\"")
5 (* end *) 5 (* end *)
6 6
108 (* end *) 108 (* end *)
109 109
110 (* begin eval *) 110 (* begin eval *)
111 length strings 111 length strings
112 (* end *) 112 (* end *)
113
114 (* And lists make a good setting for demonstrating higher-order functions and local functions. (This example also introduces one idiosyncrasy of Ur, which is that "map" is a keyword, so we name our "map" function "mp.") *)
115
116 (* begin hide *)
117 fun show_list [t] (_ : show t) : show (list t) =
118 mkShow (let
119 fun shower (ls : list t) =
120 case ls of
121 [] => "[]"
122 | x :: ls' => show x ^ " :: " ^ shower ls'
123 in
124 shower
125 end)
126 (* end *)
127
128 fun mp [a] [b] (f : a -> b) : list a -> list b =
129 let
130 fun loop (ls : list a) =
131 case ls of
132 [] => []
133 | x :: ls' => f x :: loop ls'
134 in
135 loop
136 end
137
138 (* begin eval *)
139 mp inc numbers
140 (* end *)
141
142 (* begin eval *)
143 mp (fn s => s ^ "!") strings
144 (* end *)
145
146 (* We can define our own polymorphic datatypes and write higher-order functions over them. *)
147
148 datatype tree a = Leaf of a | Node of tree a * tree a
149
150 (* begin hide *)
151 fun show_tree [t] (_ : show t) : show (tree t) =
152 mkShow (let
153 fun shower (t : tree t) =
154 case t of
155 Leaf x => "Leaf(" ^ show x ^ ")"
156 | Node (t1, t2) => "Node(" ^ shower t1 ^ ", " ^ shower t2 ^ ")"
157 in
158 shower
159 end)
160 (* end *)
161
162 fun size [a] (t : tree a) : int =
163 case t of
164 Leaf _ => 1
165 | Node (t1, t2) => size t1 + size t2
166
167 (* begin eval *)
168 size (Node (Leaf 0, Leaf 1))
169 (* end *)
170
171 (* begin eval *)
172 size (Node (Leaf 1.2, Node (Leaf 3.4, Leaf 4.5)))
173 (* end *)
174
175 fun tmap [a] [b] (f : a -> b) : tree a -> tree b =
176 let
177 fun loop (t : tree a) : tree b =
178 case t of
179 Leaf x => Leaf (f x)
180 | Node (t1, t2) => Node (loop t1, loop t2)
181 in
182 loop
183 end
184
185 (* begin eval *)
186 tmap inc (Node (Leaf 0, Leaf 1))
187 (* end *)
188
189 (* We also have anonymous record types, as in Standard ML. The next chapter will show that there is quite a lot more going on here with records than in SML or OCaml, but we'll stick to the basics in this chapter. We will add one tantalizing hint of what's to come by demonstrating the record concatention operator "++" and the record field removal operator "--". *)
190
191 val x = { A = 0, B = 1.2, C = "hi", D = True }
192
193 (* begin eval *)
194 x.A
195 (* end *)
196
197 (* begin eval *)
198 x.C
199 (* end *)
200
201 type myRecord = { A : int, B : float, C : string, D : bool }
202
203 fun getA (r : myRecord) = r.A
204
205 (* begin eval *)
206 getA x
207 (* end *)
208
209 (* begin eval *)
210 getA (x -- #A ++ {A = 4})
211 (* end *)
212
213 val y = { A = "uhoh", B = 2.3, C = "bye", D = False }
214
215 (* begin eval *)
216 getA (y -- #A ++ {A = 5})
217 (* end *)