Mercurial > urweb
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 *) |