]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.tutorial/scl/Tutorial/X Old tutorial.md
Import org.simantics.scl.tutorial from incubator SVN repo
[simantics/platform.git] / bundles / org.simantics.scl.tutorial / scl / Tutorial / X Old tutorial.md
1 <script type="text/javascript"\r
2   src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">\r
3 </script>\r
4 \r
5 # Getting started\r
6 \r
7 SCL Console is the easiest way to access SCL in Simantics. Therefore we will\r
8 be using it all the time in this tutorial.  \r
9 \r
10 ----\r
11 \r
12 SCL Console is opened from the menu *Show View/Other/SCL Console*.\r
13 \r
14 \includegraphics[scale=0.4]{figures/ShowView.png}\r
15 \hspace{1cm}\r
16 \includegraphics[scale=0.4]{figures/ShowView2.png}\r
17 \r
18 The view that is opened looks like this:\r
19 \r
20 \includegraphics[scale=0.5]{figures/SCLConsole.png}\r
21 \r
22 SCL commands are written to the box at the bottom of the view and the command responses\r
23 are shown in the upper part of the view. Try writing\r
24 ~~~\r
25 > 1 + 1\r
26 ~~~\r
27 and press enter.\r
28 \r
29 \r
30 ----\r
31 If the current command in the SCL Console input box contains an error, it is shown with a red underline.\r
32 Moving the mouse pointer to that position shows an error description:\r
33 \r
34 \includegraphics[scale=0.5]{figures/ConsoleError.png}\r
35 \r
36 When the command contains an errors, the console is not willing to execute it. Pressing *enter*\r
37 adds a new line to the command.\r
38 \r
39 While editing the command, arrow keys can be used to move the cursor around. \r
40 Pressing *ctrl-enter* adds a new line even if the command is currently valid.\r
41 Pressing *ctrl* and arrow keys up or down, you can browse the previously entered commands. \r
42 \r
43 Also copy *ctrl-C*, paste and cut work in the editing area.\r
44 \r
45 \r
46 ----\r
47 ### Exercise\r
48 \r
49 Run a multiline command:\r
50 ~~~\r
51 > for [1..10] (\x -> \r
52       for [1..x] (\y ->\r
53           print (show x + " + " + show y + " = " + show (x+y))\r
54       )\r
55   )   \r
56 ~~~\r
57 Then find it from the history and modify it to show multiplications instead of additions.\r
58 \r
59 \r
60 ----\r
61 ### Remark\r
62 We will show lots of examples of SCL code in this tutorial. If some explanation leaves\r
63 you in uncertain state, copy some of the examples to the console and \r
64 play with them.\r
65 \r
66 \r
67 ## Basic expressions\r
68 \r
69 We start from the basic mathematical expressions you can write in SCL.\r
70 This should cover the most needs you have if you want to use SCL expressions\r
71 in component types.\r
72 \r
73 ----\r
74 Writing mathematical formulas in SCL is mostly unsurprising.\r
75 ~~~\r
76 > 3*7+1\r
77 22\r
78 > 2 - sqrt 2\r
79 0.5857864376269049\r
80 > cos pi\r
81 -1.0\r
82 ~~~\r
83 \r
84 One difference from many programming languages is that parentheses are not required around the \r
85 parameters and multiple parameters are separated by whitespace:\r
86 ~~~\r
87 > atan2 1 1\r
88 0.7853981633974483\r
89 ~~~\r
90 \r
91 Parentheses are needed for each parameter separately, if the parameter is\r
92 more complicated expression than  constant or variable:\r
93 ~~~\r
94 > atan2 (sin 0.4) (cos 0.4)\r
95 0.4\r
96 ~~~\r
97 \r
98 \r
99 ----\r
100 ### Exercise\r
101 What is wrong with the following code. How to fix it?\r
102 ~~~\r
103 > sin -1\r
104 ~~~\r
105 \r
106 ----\r
107 The results of the computations can be bound to variables and used in subsequent expressions:\r
108 ~~~\r
109 > m = 4.0\r
110 > c = 2.998e8\r
111 > energy = m * c^2\r
112 > energy\r
113 3.5952016E17\r
114 ~~~\r
115 \r
116 If the variable is bound multiple times, the latest definition is used:\r
117 ~~~\r
118 > a = 4\r
119 > a = 8\r
120 > a\r
121 8\r
122 ~~~\r
123 \r
124 \r
125 ----\r
126 ### Remark\r
127 Replacing a variable binding with a new binding is a feature of SCL Console.\r
128 In SCL modules, variables can be bound only once.\r
129 \r
130 ----\r
131 A variable name must begin with a *lower-case* letter or an underscore.\r
132 Following that can be any number of letters (lower-case and upper-case), numbers and underscores.\r
133 The following names are reserved and cannot be used as identifiers:\r
134 `_`, `forall`, `if`, `then`, `else`,\r
135 `where`, `by`, `do`, `mdo`, `class`, `effect`,\r
136 `match`, `with`, `instance`, `deriving`,\r
137 `data`, `type`, `infix`, `infixl`, `infixr`.\r
138 `import`, `include`, `importJava`, `as`.\r
139 \r
140 \r
141 ----\r
142 \r
143 This is the list of arithmetical functions available in SCL. The middle column\r
144 contains the types of the functions. You can ignore them now.\r
145 \r
146 <table><tr><td>\r
147 zero </td><td> Additive a => a </td><td> additive neutral element </td></tr><tr><td> \r
148 (+) </td><td> Additive a => a -> a -> a </td><td> addition </td></tr><tr><td>\r
149 sum </td><td> Additive a => [a] -> a </td><td> sum of list elements </td></tr><tr><td>\r
150 neg </td><td> Ring a => a -> a </td><td> negation </td></tr><tr><td>\r
151 (-) </td><td> Ring a => a -> a -> a </td><td> difference </td></tr><tr><td>\r
152 one </td><td> Ring a => a </td><td> multiplicative neutral element </td></tr><tr><td>\r
153 (*) </td><td> Ring a => a -> a -> a </td><td> multiplication </td></tr><tr><td>\r
154 fromInteger </td><td> Ring a => Integer -> a </td><td> converts an integer to another number format </td></tr><tr><td>\r
155 abs </td><td> OrderedRing a => a -> a </td><td> absolute value </td></tr><tr><td>\r
156 (/) </td><td> Real a => a -> a -> a </td><td> division </td></tr><tr><td>\r
157 (`^`) </td><td> Real a => a -> a -> a </td><td> exponentiation </td></tr><tr><td>\r
158 pi </td><td> Real a => a </td><td> $\pi$ </td></tr><tr><td>\r
159 sqrt </td><td> Real a => a -> a </td><td> square root </td></tr><tr><td>\r
160 exp </td><td> Real a => a -> a </td><td> exponent function </td></tr><tr><td>\r
161 log </td><td> Real a => a -> a </td><td> natural logarithm </td></tr><tr><td>\r
162 sin,cos,tan </td><td> Real a => a -> a </td><td> trigonometric functions </td></tr><tr><td>\r
163 asin,acos,atan </td><td> Real a => a -> a </td><td> inverse trigonometric functions </td></tr><tr><td>\r
164 atan2 </td><td> Real a => a -> a -> a </td><td> arctangent with two parameters </td></tr><tr><td>\r
165 sinh,cosh,tanh </td><td> Real a => a -> a </td><td> hyperbolic functions </td></tr><tr><td>\r
166 asinh,acosh,atanh </td><td> Real a => a -> a </td><td> inverse hyperbolic functions </td></tr><tr><td>\r
167 fromDouble </td><td> Real a => Double -> a </td><td> converts a double to another number format </td></tr><tr><td>\r
168 floor </td><td> Real a => a -> a </td><td> the largest previous integer </td></tr><tr><td>\r
169 ceil </td><td> Real a => a -> a </td><td> the smallest following integer </td></tr><tr><td>  \r
170 div </td><td> Integer a => a -> a -> a </td><td> integer division </td></tr><tr><td>\r
171 mod </td><td> Integer a => a -> a -> a </td><td> integer remainer\r
172 </td></tr></table>\r
173 \r
174 Their meaning is mostly self-explanatory. \r
175 Real and integer divisions are two different functions:\r
176 ~~~\r
177 > 5 / 2\r
178 2.5\r
179 > 5 `div` 2\r
180 2\r
181 ~~~\r
182 The hat `^` is exponentiation:\r
183 ~~~\r
184 > 3^4\r
185 81.0\r
186 ~~~ \r
187 Negation function `neg` can be used with the unary minus syntax. So the following are equivalent:\r
188 ~~~\r
189 > neg 3\r
190 -3\r
191 > -3\r
192 -3\r
193 ~~~\r
194 \r
195 \r
196 ----\r
197 ### Remark\r
198 At this point you may encounter the following problem:\r
199 ~~~\r
200 > a = 2\r
201 > b = 3.4\r
202 > a + b\r
203 ~~~\r
204 The console does not execute the last expression because it contains an error \r
205 ``Expected $\langle$Integer$\rangle$ got $\langle$Double$\rangle$''.\r
206 This is because the variable `a` is bound to an integer value and `b` is bound to a double value\r
207 and SCL does automatic number conversion only for numerical literals (2, 3.4 etc.). There are several ways to fix\r
208 the problem. First is to define `a` as a double:\r
209 ~~~\r
210 > a = 2.0\r
211 ~~~\r
212 or\r
213 ~~~\r
214 > a = 2 :: Double\r
215 ~~~\r
216 Another way is to convert the integer value to double in the final expression:\r
217 ~~~\r
218 > fromInteger a + b\r
219 5.4\r
220 ~~~\r
221 \r
222 \r
223 ----\r
224 \r
225 Numbers and many other objects can be compared with the following functions:\r
226 <table><tr><td>\r
227 (==) </td><td> Eq a => a -> a -> Boolean </td><td> equality </td></tr><tr><td> \r
228 (!=) </td><td> Eq a => a -> a -> Boolean </td><td> inequality </td></tr><tr><td>\r
229 (<),(>) </td><td> Ord a => a -> a -> Boolean </td><td> strict comparison </td></tr><tr><td>\r
230 (<=),(>=) </td><td> Ord a => a -> a -> Boolean </td><td> non-strict comparison </td></tr><tr><td>\r
231 min </td><td> Ord a => a -> a -> a </td><td> returns the the smaller of two parameters </td></tr><tr><td>\r
232 max </td><td> Ord a => a -> a -> a </td><td> returns the larger of two parameters </td></tr><tr><td>\r
233 compare </td><td> Ord a => a -> a -> Integer </td><td> returns -1 (0, 1), if the first parameter is smaller (equal, bigger) than the second one\r
234 </td></tr></table>\r
235 For example:\r
236 \r
237 ~~~\r
238 > 1 < 2\r
239 True\r
240 > 6 < 4\r
241 False\r
242 > max 1.5 3.8\r
243 3.8\r
244 ~~~\r
245 \r
246 \r
247 ----\r
248 Boolean expressions can be used to write conditional expressions:\r
249 ~~~\r
250 > a = 3\r
251 > b = 4\r
252 > if a < b then a else b\r
253 3\r
254 > a = 5\r
255 > if a < b then a else b\r
256 4\r
257 ~~~\r
258 In order to test multiple conditions, if-expressions can be combined:\r
259 ~~~\r
260 > if a < b \r
261   then -1\r
262   else if a > b\r
263   then 1\r
264   else 0\r
265 1\r
266 ~~~\r
267 \r
268 \r
269 ----\r
270 Boolean values can be combined with conjunction `&&`, disjunction `||` and negation `not`.\r
271 ~~~\r
272 > True && False\r
273 False\r
274 > True || False\r
275 True\r
276 > not True\r
277 False\r
278 ~~~\r
279 \r
280 \r
281 ----\r
282 \r
283 Strings are written by enclosing them into double quotes:\r
284 ~~~\r
285 > "Hello world!"\r
286 "Hello world!"\r
287 ~~~\r
288 \r
289 Some of the operators seen so far can also be applied to strings:\r
290 ~~~\r
291 > "Hello" + " world!"\r
292 "Hello world!"\r
293 > "Foo" < "Bar"\r
294 False\r
295 ~~~\r
296 \r
297 There are also many functions specific to strings. We will however \r
298 describe just some of them:\r
299 <table><tr><td>\r
300 length </td><td> String -> Integer </td><td> the length of a string </td></tr><tr><td>\r
301 substring </td><td> String -> Integer -> Integer -> String </td><td> returns a substring of the string\r
302                                                      when the begin and the end positions of the\r
303                                                      string are given </td></tr><tr><td>\r
304 show </td><td> Show a => a -> String </td><td> converts a value to a string </td></tr><tr><td> \r
305 read </td><td> Read a => String -> a </td><td> converts a string to a value </td></tr><tr><td>\r
306 indexOf </td><td> String -> String -> Integer </td><td> the index of the first position in the string that matches the given string </td></tr><tr><td>\r
307 lastIndexOf </td><td> String -> String -> Integer </td><td> the index of the last position in the string that matches the given string </td></tr><tr><td>\r
308 startsWith </td><td> String -> String -> Boolean </td><td> checks if the string starts with the given prefix </td></tr><tr><td>\r
309 trim </td><td> String -> String </td><td> removes the white space from the beginning and end of the string\r
310 </td></tr></table>\r
311 From these functions, we need only `show` in this tutorial. \r
312 \r
313 ~~~\r
314 > x = 5.7\r
315 > "x = " + show x\r
316 x = 5.7\r
317 ~~~\r
318 \r
319 \r
320 ## Functions\r
321 \r
322 In SCL, functions are first-class values that can be manipulated with the\r
323 same ease as numbers and other values. Almost all control structures also\r
324 require that you define your own functions. Therefore we describe them\r
325 before going to other data structures.\r
326 \r
327 ----\r
328 The syntax of the function definitions in SCL resemble function definitions in mathematics:\r
329 ~~~\r
330 > dist x y = abs (x - y)\r
331 > dist 2 5\r
332 3\r
333 > dist 6 4\r
334 2\r
335 ~~~\r
336 \r
337 \r
338 ----\r
339 ### Exercise\r
340 Define a generalized average function:\r
341 $${\rm avgG}\ p\ x\ y = \left({x^p + y^p \over 2}\right)^{1 \over p}$$\r
342 Check that it works correctly:\r
343 ~~~\r
344 > avgG 1 3 5\r
345 4.0\r
346 > avgG 2 2 14\r
347 10.0\r
348 > avgG (-1) 3 6\r
349 4.0\r
350 ~~~\r
351 \r
352 \r
353 ----\r
354 \r
355 Functions can be recursive. For example Euclid's algorithm for\r
356 computing greatest common divisor for two integers can be implemented\r
357 as:\r
358 ~~~\r
359 > gcd a b = if a > b\r
360             then gcd b a\r
361             else if a == 0\r
362             then b\r
363             else gcd (b `mod` a) a\r
364 > gcd 12 9\r
365 3           \r
366 ~~~\r
367 \r
368 \r
369 ----\r
370 ### Exercise\r
371 Implement a function `fib` for computing Fibonacci numbers. First two Fibonacci numbers\r
372 are one and after that every Fibonacci number is the sum of two previous Fibonacci numbers:\r
373 1, 1, 2, 3, 5, 8, 13, \ldots.  \r
374 \r
375 \r
376 ----\r
377 Many functions are implemented by cases. In these situations function definition can be\r
378 written as multiple separate equations:\r
379 ~~~\r
380 > gcd a b | a > b = gcd b a\r
381   gcd 0 b         = b\r
382   gcd a b         = gcd (b `mod` a) a\r
383 ~~~\r
384 In this way it is easier to verify that every individual equation is corrent.\r
385 \r
386 There are two ways to restrict the applicability of an equation.\r
387 The first way is to use patterns as parameters instead of just variables.\r
388 In the example above, the second equation has a constant pattern 0 as a first parameter.\r
389 We see later more complicated patterns.\r
390 The second way to restrict the applicability is to add guards to the equation. \r
391 A guard is the part in the first equation above after the vertical bar and before the equality.\r
392 It is a boolean condition that must be true for equation to be applicable.\r
393 \r
394 The actual function value is computed by the first equation that can be applied with the given parameters. \r
395 \r
396 \r
397 ----\r
398 ### Exercise\r
399 Rewrite the Fibonacci's function using either constant patterns or guards.\r
400 \r
401 \r
402 ----\r
403 One of the cornerstones of all functional programming languages, including SCL, is the ability\r
404 to give functions as parameters to other functions:\r
405 ~~~\r
406 > epsilon = 1e-9\r
407 > der f x = (f (x + epsilon) - f (x - epsilon)) / (2*epsilon)\r
408 > der sin 0\r
409 1.0\r
410 > der log 5\r
411 0.2000000165480742\r
412 ~~~\r
413 This kind of functions are called *higher order functions*.\r
414 \r
415 Here is another example:\r
416 ~~~\r
417 > iterate f n x | n > 0     = iterate f (n-1) (f x)\r
418                 | otherwise = x\r
419 > collatz n | n `mod` 2 == 0 = n `div` 2\r
420             | otherwise      = 3*n + 1\r
421 > iterate collatz 0 13\r
422 13\r
423 > iterate collatz 1 13\r
424 40\r
425 > iterate collatz 2 13\r
426 20\r
427 > iterate collatz 5 13\r
428 16\r
429 > iterate collatz 8 13\r
430 2\r
431 > iterate collatz 9 13\r
432 1\r
433 ~~~\r
434 \r
435 \r
436 ----\r
437 Often the function we want to define can be get by filling some parameters of an already existing function.\r
438 For example a function `limitZero`, that returns zero if its parameter is negative and otherwise\r
439 returns the parameter unmodified, can be defined as:\r
440 ~~~\r
441 > limitZero = max 0.0\r
442 > limitZero 2.1\r
443 2.1\r
444 > limitZero (-5.4)\r
445 0.0\r
446 ~~~\r
447 This is called *partial application*.\r
448 \r
449 \r
450 ----\r
451 Binary operators can be referred and partially applied by enclosing them\r
452 in parenthesis:\r
453 ~~~\r
454 > f = (+)\r
455 > f 1 2\r
456 3\r
457 > incByOne = (+) 1\r
458 > incByOne 5\r
459 6\r
460 ~~~\r
461 \r
462 Inversely, an ordinary function can be used as a binary operator by enclosing it\r
463 to backquotes (in fact, we have seen it already in the definiton of `gcd`):\r
464 ~~~\r
465 > 1 `f` 2\r
466 3\r
467 > 14 `div` 3\r
468 4\r
469 ~~~\r
470 \r
471 \r
472 ----\r
473 Functions can be also defined without giving them a name:\r
474 ~~~\r
475 > \x -> x * 2\r
476 <function>\r
477 > (\x -> x * 2) 3\r
478 6\r
479 ~~~\r
480 \r
481 This is useful when using higher order functions:\r
482 ~~~\r
483 > der (\x -> x^2 - 5*x) 2\r
484 -1.000000082740371\r
485 ~~~\r
486 \r
487 \r
488 ----\r
489 For writing complex functions, it is necessary to define auxiliary\r
490 variables. There are two ways of doing this in SCL. The first way is\r
491 `where` syntax:\r
492 ~~~\r
493 > dist x1 y1 x2 y2 = sqrt (dx*dx + dy*dy)\r
494     where\r
495       dx = x1-x2\r
496       dy = y1-y2      \r
497 ~~~\r
498 The second way is `do` syntax\r
499 ~~~\r
500 > dist x1 y1 x2 y2 = do\r
501       dx = x1-x2\r
502       dy = y1-y2\r
503       sqrt (dx*dx + dy*dy)      \r
504 ~~~\r
505 The difference between these constructs is often only aesthetic.\r
506 \r
507 One feature of SCL that is imporant here is that SCL uses\r
508 the layout (indentation) of the code for parsing. The statements\r
509 in the same `where` or `do` block must be consistently\r
510 indented and indentation must be larger than the enclosing context.\r
511 \r
512 \r
513 ----\r
514 \r
515 SCL standard library defines the following functions for\r
516 manipulating functions:\r
517 <table><tr><td>\r
518 id </td><td> a -> a </td><td> identity function </td></tr><tr><td>\r
519 (\$) </td><td> (a -> <e> b) -> a -> <e> b </td><td> application operator </td></tr><tr><td>\r
520 (.) </td><td> (b -> <e> c) -> (a -> <e> b) -> (a -> <e> c) </td><td> function composition </td></tr><tr><td>\r
521 const </td><td> a -> b -> a </td><td> constant function </td></tr><tr><td>\r
522 curry </td><td> ((a, b) -> <e> c) -> a -> b -> <e> c </td><td> give function parameters separately instead of a pair </td></tr><tr><td>\r
523 uncurry </td><td> (a -> b -> <e> c) -> ((a, b) -> <e> c)  </td><td> inverse of curry </td></tr><tr><td>\r
524 curry3 </td><td> ((a, b, c) -> <e> d) -> a -> b -> c -> <e> d  </td><td> give function parameters separately instead of a tripl </td></tr><tr><td>\r
525 uncurry3 </td><td> (a -> b -> c -> <e> d) -> ((a, b, c) -> <e> d) </td><td> inverse of curry3  </td></tr><tr><td>\r
526 flip </td><td> (a -> b -> <e> c) -> b -> a -> <e> c </td><td> flips the order of the function parameters\r
527 </td></tr></table>\r
528 Function `$` just applies given function and a parameter:\r
529 \r
530 ~~~\r
531 f $ x = f x\r
532 ~~~\r
533 \r
534 The precedence of the operator is very weak and it associates\r
535 to right. It can be used\r
536 to remove some parentheses in deeply nested expression. So\r
537 we can write\r
538 \r
539 ~~~\r
540 > text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."\r
541 > length \r
542     $ filter (\s -> length s > 4) \r
543     $ splitString text "[ ,.]"\r
544 5\r
545 ~~~\r
546 \r
547 instead of\r
548 \r
549 ~~~\r
550 > length (filter (\s -> length s > 4) (splitString text "[ ,.]"))\r
551 5\r
552 ~~~\r
553 \r
554 \r
555 ## Data structures\r
556 \r
557 ----\r
558 One of the simplest data structure is a pair:\r
559 ~~~\r
560 > ("Citizen Kane", 1941)\r
561 ("Citizen Kane", 1941)\r
562 ~~~\r
563 As seen above, the different elements of the pair can have different types. \r
564 \r
565 The components of the pair can be accessed with the functions `fst` and `snd`:\r
566 ~~~\r
567 > fst ("Citizen Kane", 1941)\r
568 "Citizen Kane"\r
569 > snd ("Citizen Kane", 1941)\r
570 1941\r
571 ~~~\r
572 \r
573 Other tuple lenghts are also supported:\r
574 ~~~\r
575 > ()\r
576 ()\r
577 > ("1", 1, 1.0)\r
578 ("1", 1, 1.0)\r
579 ~~~\r
580 \r
581 \r
582 ----\r
583 Pairs and other tuples are useful, when we want to return more than one value from a function:\r
584 ~~~\r
585 > toPolarCoordinates (x,y) = (sqrt (x*x + y*y), atan2 y x)\r
586 > toRectangularCoordinates (r,angle) = (r*cos angle, r*sin angle)\r
587 > polar = toPolarCoordinates (3,-6)\r
588 > polar\r
589 (6.708203932499369, -1.1071487177940904)\r
590 > toRectangularCoordinates polar\r
591 (3.000000000000001, -6.0)\r
592 ~~~\r
593 \r
594 As seen in the above example, when tuples are given as parameters to the functions, they can\r
595 be pattern matched. In `toPolarCoordinates (x,y)` the components of the pair given\r
596 as a parameter to the function are bound to `x` and `y`. \r
597 A much less readable version of the above function would be:\r
598 ~~~\r
599 > toPolarCoordinates p = (sqrt (fst p*fst p + snd p*snd p), \r
600                           atan2 (snd p) (fst p))\r
601 ~~~\r
602 \r
603 Patterns can be nested. A nonsensical example: \r
604 ~~~\r
605 > shuffle ((a,b), (c,d)) = ((c,b), (a,d))\r
606 > shuffle ((1,2), (3,4))\r
607 ((3, 2), (1, 4))\r
608 ~~~\r
609 \r
610 \r
611 ----\r
612 ### Remark\r
613 The following command produces an error ``Expected $\langle$Integer$\rangle$ got $\langle$String$\rangle$\r
614 ~~~\r
615 > shuffle (("1","2"), ("3","4"))\r
616 ~~~\r
617 althought the function definition doesn't seem to care about the contents of the values (even if they are all of different types).\r
618 This is a restriction of the current version of SCL Console: all functions you define are *monomorphic* meaning\r
619 that all types involved must be fully known. When this is not a case, the compiler chooses the types somewhat arbitrarily.\r
620 In SCL modules, there is no such restrictions and the compiler chooses the most generic type as possible for a function.\r
621 Therefore, if the `shuffle` were defined in a SCL module, the above command would work.\r
622 \r
623 ----\r
624 Maybe the most important datatype is a list that may \r
625 hold any number of values of the same type. Lists\r
626 are constructed by enclosing the values in brackets:  \r
627 ~~~\r
628 > [1, 2, 3, 4]\r
629 [1, 2, 3, 4]\r
630 ~~~\r
631 \r
632 Elements of the lists are accessed with `!` operator:\r
633 ~~~\r
634 > l = [1, 2, 3]\r
635 > l!0\r
636 1\r
637 > l!2\r
638 3\r
639 ~~~\r
640 The length of the list can be found out with `length`:\r
641 ~~~\r
642 > length l\r
643 3\r
644 ~~~\r
645 \r
646 Two lists are joined together with `+` operator:\r
647 ~~~\r
648 > [1, 2] + [3, 4]\r
649 [1, 2, 3, 4]\r
650 ~~~\r
651 \r
652 Finally, a list containing some range of integers can be constructed as\r
653 ~~~\r
654 > [4..9]\r
655 [4, 5, 6, 7, 8, 9]\r
656 ~~~\r
657 \r
658 \r
659 ----\r
660 ### Exercise\r
661 A quadratic equation $a x^2 + b x + c = 0$ has real solutions only if the discriminant\r
662 $\Delta = b^2 - 4ac$ is non-negative. If it is zero, the equation has one solution and\r
663 if it is positive, the equation has two solutions:\r
664 $${-b \pm \sqrt{\Delta} \over 2a}.$$\r
665 Write a function $`solveQuadratic`$ that solves a quadratic function whose\r
666 coefficients are given as parameters and returns a list containing all solutions\r
667 of the equation:\r
668 ~~~\r
669 > solveQuadratic 1 1 (-2)\r
670 [1.0, -2.0]\r
671 > solveQuadratic 1 1 1\r
672 []\r
673 ~~~\r
674 \r
675 \r
676 ----\r
677 Many useful tools for manipulating lists are higher order functions.\r
678 The function `map` applies a given function to all elements of a list\r
679 and produces a new list of the same length from the results:\r
680 $$`map`\ f\ [x_1,x_2,\ldots,x_n] = [f\ x_1,f\ x_2,\ldots,f\ x_n]$$\r
681 Here is couple of examples:\r
682 ~~~\r
683 > map (\s -> "_" + s + "_") ["a", "b", "c"]\r
684 ["_a_", "_b_", "_c_"]\r
685 > map ((*) 3) [1..4]\r
686 [3, 6, 9, 12]\r
687 ~~~\r
688 \r
689 Unwanted elements can be removed from a list by `filter` function:\r
690 ~~~\r
691 > filter (\s -> length s > 4) ["small", "big", "large", "tiny"]\r
692 ["small", "large"]\r
693 > isPrime p = filter (\d -> p `mod` d == 0) [2..p-1] == []\r
694 > filter isPrime [2..20]\r
695 [2, 3, 5, 7, 11, 13, 17, 19]\r
696 ~~~\r
697 \r
698 The function `foldl` computes an aggergate value over a list of values\r
699 by applying a binary function to the elements starting from the given initial element:\r
700 $${\tt foldl}\ (\oplus)\ x_0\ [x_1,x_2,\ldots,x_n] = (\cdots((x_0 \oplus x_1) \oplus x_2) \oplus \cdots \oplus x_n)$$\r
701 In practice:\r
702 ~~~\r
703 > foldl (+) 0 [2,3,4]\r
704 9\r
705 > foldl (*) 1 [2,3,4]\r
706 24\r
707 > foldl max 0 [2,3,4]\r
708 4\r
709 ~~~\r
710 The function `sum` is equivalent to `foldl (+) zero`, but is in \r
711 some cases implemented much more effeciently (for example for strings).\r
712 \r
713 The function `concatMap` is similar to `map`, but it assumes\r
714 that the given function produces lists and concatenates the lists together:\r
715 ~~~\r
716 > concatMap \r
717       (\(n,v) -> map (const v) [1..n]) \r
718       [(3,"a"), (2,"l"), (1,"i")]\r
719 ["a", "a", "a", "l", "l", "i"]\r
720 ~~~\r
721 \r
722 \r
723 ----\r
724 ### Exercise\r
725 Define a generalized average function for lists:\r
726 $${\rm avgG}\ p\ [x_1,\ldots,x_{n}] = \left({x_1^p + \cdots + x_n^p \over n}\right)^{1 \over p}$$\r
727 \r
728 \r
729 ----\r
730 ### Exercise\r
731 One useful way for producing lists is to map a range expression. For example\r
732 ~~~\r
733 > diffs (l :: [Integer]) = map (\i -> l!(i+1) - l!i) [0..length l-2]\r
734 > diffs [1,2,4,8,3]\r
735 [1, 2, 4, -5]\r
736 ~~~\r
737 Use the pattern to reimplement the function `reverse` from the standard library\r
738 that reverses the order of elements in a list.\r
739 \r
740 \r
741 ----\r
742 SCL supports *list comprehension* which allows to write\r
743 many list producing expressions with a syntax that closely\r
744 resembles the set comprehension from mathematics:\r
745 ~~~\r
746 > l = [1..3]\r
747 > [2*x | x <- l]\r
748 [2, 4, 6]\r
749 > [(x,y) | x <- l, y <- l]\r
750 [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]\r
751 > [(x,y) | x <- l, y <- l, x < y]\r
752 [(1, 2), (1, 3), (2, 3)]\r
753 > [(x,y) | x <- l, y=4-x]\r
754 [(1, 3), (2, 2), (3, 1)]\r
755 ~~~\r
756 As seen in the above examples, the left side of the vertical bar \r
757 can be any expression producing the elements of the list. The\r
758 right side of the bar is a list of producing statements:\r
759 `x <- l` considers all `x` in the list `l`,\r
760 `x = e` sets the value of `x` by the expression `e`\r
761 and any boolean expression like `x < y` filters the produced elements.\r
762 \r
763 \r
764 ----\r
765 ### Remark\r
766 SCL does not support yet pattern matching of lists althought it is supported in Haskell. \r
767 \r
768 \r
769 ----\r
770 This is a list of some list functions provided by SCL standard library:\r
771 \r
772 \r
773 <table><tr><td>\r
774 map </td><td> Functor a => (a -> b) -> f a -> f b </td><td> </td></tr><tr><td>\r
775 concatMap </td><td> (a -> <e> [b]) -> [a] -> <e> [b] </td><td> </td></tr><tr><td>\r
776 filter </td><td> (a -> <e> Boolean) -> [a] -> <e> [a] </td><td> </td></tr><tr><td>\r
777 filterJust </td><td> [Maybe a] -> [a] </td><td> </td></tr><tr><td>\r
778 foldl </td><td> (a -> b -> <e> a) -> a -> [b] -> <e> a </td><td> apply the given binary operation from left to right </td></tr><tr><td>\r
779 foldl1 </td><td> (a -> a -> <e> a) -> [a] -> <e> a </td><td> </td></tr><tr><td>\r
780 unfoldl </td><td> (b -> <e> Maybe (a, b)) -> b -> <e> [a] </td><td> </td></tr><tr><td>\r
781 unfoldr </td><td> (b -> <e> Maybe (a, b)) -> b -> <e> [a] </td><td> </td></tr><tr><td>\r
782 zip </td><td> [a] -> [b] -> [(a,b)] </td><td> combine elements in the two lists </td></tr><tr><td>\r
783 zipWith </td><td> (a -> b -> <e> c) -> [a] -> [b] -> <e> [c] </td><td> </td></tr><tr><td>\r
784 unzip </td><td> [(a,b)] -> ([a],[b]) </td><td> </td></tr><tr><td>\r
785 sort </td><td> Ord a => [a] -> [a] </td><td> sorts the elements in the list </td></tr><tr><td>\r
786 sortBy </td><td> Ord b => (a -> <e> b) -> [a] -> <e> [a] </td><td> sorts the elements by a given criteria </td></tr><tr><td>\r
787 sortWith </td><td> (a -> a -> <e> Integer) -> [a] -> <e> [a] </td><td> sorts the elements by a given comparison function </td></tr><tr><td>\r
788 (\\) </td><td> Eq a => [a] -> [a] -> [a] </td><td> removes from the first list the elements that occur in the second list </td></tr><tr><td>\r
789 range </td><td> Integer -> Integer -> [Integer] </td><td> </td></tr><tr><td>\r
790 reverse </td><td> [a] -> [a] </td><td> reverses the order of the elements in the list </td></tr><tr><td>\r
791 take </td><td> Integer -> [a] -> [a] </td><td> returns $n$ first elements of the list </td></tr><tr><td>\r
792 drop </td><td> Integer -> [a] -> [a] </td><td> removes $n$ first elements from the list and returns the tail </td></tr><tr><td>\r
793 lookup </td><td>  Eq a => a -> [(a, b)] -> Maybe b </td><td> finds a pair from the list such that the first component\r
794                                              matches the given value and returns the second component </td></tr><tr><td>\r
795 and </td><td> [Boolean] -> Boolean </td><td> </td></tr><tr><td>\r
796 or </td><td> [Boolean] -> Boolean </td><td> </td></tr><tr><td>\r
797 any </td><td> (a -> <e> Boolean) -> [a] -> <e> Boolean </td><td> </td></tr><tr><td>\r
798 all </td><td> (a -> <e> Boolean) -> [a] -> <e> Boolean \r
799 </td></tr></table>\r
800 \r
801 \r
802 ----\r
803 One data structure used quite often is an optional value.\r
804 It is useful, if the function produces the result only for\r
805 some parameter values. Optional value is either \r
806 `Just value` or `Nothing`. Here is an example:\r
807 ~~~\r
808 > safeSqrt x | x >= 0    = Just (sqrt x)\r
809              | otherwise = Nothing\r
810 > safeSqrt 2\r
811 Just 1.4142135623730951\r
812 > safeSqrt (-2)\r
813 Nothing   \r
814 ~~~\r
815 The type of the expressions  `Just value` and `Nothing` is `Maybe t`,\r
816 where $`t`$ is the type of `value`.\r
817 \r
818 Optional values can be handled with pattern matching\r
819 (the example is from the standard library):\r
820 ~~~\r
821 > fromMaybe _ (Just value)  = value\r
822   fromMaybe default Nothing = default\r
823 ~~~\r
824 \r
825 \r
826 ----\r
827 Sometimes it is useful to use pattern matching without\r
828 defining a new function for it. Therefore there is\r
829 `match` construct:\r
830 ~~~\r
831 > match (1,2,3) with\r
832      (x,y,z) -> x+y+z\r
833 6\r
834 ~~~\r
835 As with functions, there can be multiple cases and the\r
836 first matching case is chosen:\r
837 ~~~\r
838 > match safeSqrt 3 with\r
839       Just v  -> v\r
840       Nothing -> fail "Something bad happened." \r
841 ~~~\r
842 \r
843 ## Types\r
844 \r
845 ----\r
846 \r
847 Every expression in SCL has a type. Type determines the set of possible values\r
848 of the expression. They are used for detecting errors in SCL code, for choosing the\r
849 right implementation of a method (for example addition `(+)`) and for generating\r
850 efficient byte code.\r
851 \r
852 When the type is monomorphic (does not contain type variables), it can be printed as\r
853 ~~~\r
854 > typeOf "foo"\r
855 String\r
856 > typeOf [1,2,3]\r
857 [Integer]\r
858 ~~~\r
859  \r
860 \r
861 ----\r
862 Normally SCL compiler will infer the types of the expressions automatically and\r
863 you don't have to specify them manually. There are however situations where\r
864 explicit control of types is useful:\r
865 * You want to document the interface of your functions. It is good practice\r
866   to write a type annotation for all top-level functions declared in a SCL module.\r
867   Such declarations are not available in SCL Console: \r
868   ~~~\r
869   fst :: (a,b) -> a\r
870   fst (x,y) = x\r
871   ~~~\r
872 * SCL compiler cannot infer a type that satisfies all the required constraints:\r
873   ~~~\r
874   > strId x = show (read x)\r
875   There is no instance for <Show ?a>.\r
876   There is no instance for <Read ?a>.\r
877   > strId x = show (read x :: Integer)\r
878   > strId "1"\r
879   "1"\r
880   > strId "1.0"\r
881   java.lang.NumberFormatException: For input string: "1.0"\r
882   ...\r
883   > strId x = show (read x :: Double)\r
884   > strId "1"\r
885   "1.0"\r
886   > strId "1.0"\r
887   "1.0"\r
888   ~~~\r
889   The type annotation is needed here, because `read` parses a string\r
890   to a certain type of values, `show` converts it back to string,\r
891   and the behavior of the composition depends on what the intermediate type is.\r
892   There is however not enough information for the compiler to infer the type\r
893   (it is shown as `?a` in the error message). \r
894 * Code specialized to a certain type may be more efficient than a generic code\r
895   that applies to all data types.\r
896 A type of an expression or identifier is annotated by adding `::` and a type\r
897 expression after it. Type annotations may also be used in patterns:\r
898 ~~~\r
899 sign (x :: Double) = compare x 0 \r
900 ~~~\r
901 \r
902 \r
903 ----\r
904 The following types (or more exactly, type constructors) are built in the SCL compiler:\r
905 * `Boolean`\r
906 * `Byte`, `Short`, `Integer`, `Long`\r
907 * `Float`, `Double`\r
908 * `String`\r
909 * `[]`\r
910 * `()`, `(,)`, `(,,)`, ...\r
911 * `(->)`\r
912 * `Maybe`\r
913 * `Array`\r
914 * `BooleanArray`, `ByteArray`, `ShortArray`, \r
915   `IntegerArray`, `LongArray`, `FloatArray`, `DoubleArray`\r
916 \r
917 Other type constructors are defined in SCL modules, either importing them from Java\r
918 or using `data` declaration.\r
919 Except for the couple of special cases in the previous list, the names of \r
920 all type constructors are capitalized.\r
921 \r
922 Some type constructors are parametric (compare to generics in Java or templates in C++).\r
923 For example, the list type constructor `[]` has one parameter: the type of the list\r
924 elements. Thus `[Integer]` is the type of the integer lists and `[String]` \r
925 is the type of string lists. \r
926 `[[Integer]]` is the type of the lists of integer\r
927 lists. Parameters are usually written after the parametric type constructor: \r
928 for example `Maybe Integer` or `Array String`, but some of the builtin type \r
929 constructors can be written in a special way in order to make the type \r
930 expressions more readable:\r
931 ~~~\r
932 [a] = [] a\r
933 (a,b) = (,) a b\r
934 (a,b,c) = (,,) a b c\r
935 ...\r
936 a -> b = (->) a b\r
937 ~~~\r
938 \r
939 Particularly important type constructor is `(->)` for building function types.\r
940 For example, the type of the function computing the length of a string is `String -> Integer`: \r
941 the function takes a string as a parameter and returns an integer.\r
942 \r
943 Types of the functions taking multiple parameters are written by composing function types. \r
944 For example, the type of a function taking nth element of a string list is \r
945 `[String] -> Integer -> String`. The function takes a string list and an integer as\r
946 a parameter and returns a string. Function type operator `->` is right associative\r
947 thus the previous type is equivalent to `[String] -> (Integer -> String)`. \r
948 Thus the type expression can be read as well as a type of functions taking a string\r
949 list and returning another function from integers and strings.\r
950 \r
951 `(a,b)` is the type of pairs where the first component of the pair has type `a`\r
952 and the second component has type `b`. Tuple types `(a,b,c)`, `(a,b,c,d)` etc. \r
953 are defined similarly. `Maybe a` is the type of optional values.\r
954 \r
955 \r
956 ----\r
957 Many functions can be defined so that they do not need to know the exact types they are operating with.\r
958 Such unknown types can be filled in type expressions by type variables: for example the function\r
959 we discussed earlier that took nth element of a string list does not need the information that\r
960 list elements are strings in its implementation and so it can be given a more generic type\r
961 `[a] -> Integer -> a`, i.e a function taking a list of `a`:s and an integer as a parameter\r
962 and returning a single `a`.\r
963 \r
964 Type variables may also refer to parametric types, but all useful examples involve type constraints we describe below.\r
965 \r
966 \r
967 ----\r
968 ### Exercise*\r
969 \r
970 Function types with type variables tell quite much about the function assuming it is total,\r
971 i.e does not hang or throw a runtime exception with any parameters. Write the *unique*\r
972 functions with the following type signatures:\r
973 ~~~\r
974 a -> a\r
975 (a,b) -> (b,a)\r
976 ~~~\r
977 Write all possible functions with the following type signatures:\r
978 ~~~\r
979 a -> a -> a\r
980 ~~~\r
981 \r
982 Because SCL Console does not support definition of functions with generic types,\r
983 this exercise can be done only by writing your own SCL module.\r
984 \r
985 ----\r
986 SCL does not support function overloading at least in the way Java and C++ support it.\r
987 This means that every function has a unique type signature. Now consider the addition function\r
988 `(+)`. We could defined its signature for example as `Integer -> Integer -> Integer`,\r
989 but then we would need some other name for the sum of doubles `Double -> Double -> Double` or\r
990 strings `String -> String -> String`. It would seem like the right signature would be\r
991 `a -> a -> a`, but that is not satisfactory either, because then the function had to\r
992 somehow support all possible types. \r
993 \r
994 The solution to the problem is to constraint the set of allowed types for the type variable.\r
995 Such a constrained type is written in the case of addition function as\r
996 `Additive a => a -> a -> a`. The constraint `Additive a` is composed of a type class\r
997 `Additive` followed by parameters of the constraint. \r
998 The type can be understood in two different ways. A logical reading is\r
999 > For any additive type `a`, the function takes two `a`:s as parameters and returns `a`.\r
1000 and an operational reading that gives a good intuition what is happening in runtime\r
1001 >  The function takes a parameter `Additive a` that describes a set of methods that can be used to operate the values of `a` and two `a`:s and returns `a`.\r
1002 \r
1003 Constrained type variable can also be parametric. For example, let's say we want to define a function getNth that takes nth element of a list but also works with arrays. The signature would then be\r
1004 ~~~\r
1005 getNth :: Sequence s => s a -> Integer -> a\r
1006 ~~~\r
1007 \r
1008 Type classes form a hierarchy: each class may have any number of superclasses. Only the most specific type class is needed in the constraints. For example, addition and multiplication have the following signatures:\r
1009 ~~~\r
1010 (+) :: Additive a => a -> a -> a\r
1011 (*) :: Ring a => a -> a -> a\r
1012 ~~~\r
1013 and Additive is a superclass of Ring a. A function using both operators need to specify only Ring as a constraint:\r
1014 ~~~\r
1015 doubleAndAddOne :: Ring a => a -> a\r
1016 doubleAndAddOne x = 2*x + 1\r
1017 ~~~\r
1018 \r
1019 This is a hierarchy of ``numerical'' type classes defined in the standard library of SCL:\r
1020 \r
1021 \includegraphics[scale=0.6]{figures/TypeClasses.png}\r
1022 \r
1023 The white boxes are type classes. An open arrow between type classes is the inheritance between type classes.\r
1024 The yellow boxes are types defined in the standard library. They are connected to the type classes\r
1025 they belong to.\r
1026 \r
1027 There are also type classes for converting values to strings `Show` and vice versa `Read`.\r
1028 Types in the type class `Hashable` provide a method to compute a hash code.\r
1029 Types in the type class `Serializable` can be serialized to a byte array and deserialized back to a value.\r
1030 There are also some type classes that make programming with different containers more generic:\r
1031 `Functor`, `Monad`, etc. \r
1032 \r
1033 \r
1034 ----\r
1035 SCL functions are referentially transparent which means that they are like\r
1036 mathematical functions always returning the same value for the same parameters\r
1037 and not causing any observable side-effects. This seems extremely restrictive\r
1038 because most of the programs are written in order to generate some kind of\r
1039 side-effects and even completely mathematical algorithms involve functions\r
1040 that are not referentially transparent such as generation of random numbers.\r
1041 \r
1042 This policy does not however restrict expressive power of the language because\r
1043 functions can return and manipulate *descriptions of computations*.\r
1044 These computations are then executed by some external means.\r
1045 Two different ways of handling computations in SCL are monads and effect types.\r
1046 Effect types are not applicable to as large range of different\r
1047 computation concepts as monads are but they are easier to work with.\r
1048 \r
1049 An effectful computation has type `<effects> t`.\r
1050 The type after angle brackets is the type of the value obtained by the computation.\r
1051 Side-effects that might happen during the computation are listed inside of angle brackets.\r
1052 Effect types must always occur as a return type of a function. Here are some examples (some fictional) \r
1053 of functions with side-effects:\r
1054 ~~~\r
1055 randomBetween :: Double -> Double -> <Nondet> Double\r
1056 resource :: String -> <ReadGraph> Resource\r
1057 claim :: Resource -> Resource -> Resource -> <WriteGraph> ()\r
1058 randomLiteral :: Double -> Double -> <Nondet,WriteGraph> Resource\r
1059 ~~~\r
1060 \r
1061 Effect types are much like type constraints: you can mostly ignore them when using functions.\r
1062 All effects you use are automatically collected and added to the type signature of the defined\r
1063 function (or checked against type annotation if provided).\r
1064 \r
1065 Like type classes, effects form a hierarchy. For example WriteGraph inherits ReadGraph\r
1066 and a function both reading and writing to graph is annotated only with `<WriteGraph>` effect.\r
1067 \r
1068 Like types, effects can also be abstracted with effect variables. This is important when defining generic\r
1069 functions that manipulate possibly effectful functions:\r
1070 ~~~\r
1071 executeTwice :: (() -> <e> ()) -> <e> ()\r
1072 executeTwice f = do f () ; f ()\r
1073 \r
1074 (.) :: (b -> <e2> c) -> (a -> <e1> b) -> (a -> <e1,e2> c)\r
1075 (f . g) x = f (g x)\r
1076 ~~~\r
1077 \r
1078 \r
1079 ----\r
1080 ### Exercise\r
1081 Revisit the earlier lessons listing library functions and their types. \r
1082 Can you now understand all the type signatures?\r
1083 \r
1084 \r
1085 ## Side-effects\r
1086 \r
1087 ----\r
1088 So far our examples have used pure functions without side effects.\r
1089 There are indeed quite few functions in the standard library producing\r
1090 side effects. One of them is the printing function: \r
1091 ~~~\r
1092 > print "Hello world!"\r
1093 Hello world!\r
1094 ~~~\r
1095 \r
1096 Side-effectful function applications can be sequenced \r
1097 in a `do` block:\r
1098 ~~~\r
1099 > do print "Hello,"\r
1100      print "    World!"\r
1101 Hello,\r
1102     World!     \r
1103 ~~~\r
1104 \r
1105 ----\r
1106 It is very typical that we want to cause some effect for\r
1107 every element of some list. For that purpose there is a function `for`:\r
1108 ~~~\r
1109 > for [1..3] print\r
1110 1\r
1111 2\r
1112 3\r
1113 ~~~\r
1114 \r
1115 Here is a little more complicated example:\r
1116 ~~~\r
1117 > items = ["patridge in a pear tree", "turtle doves",\r
1118            "french hens", "colly birds", "gold rings",\r
1119            "geese-a-laying", "swans-a-swimming", "maids-a-milking",\r
1120            "ladies dancing", "lords-a-leaping", "pipers piping",\r
1121            "drummers drumming"]\r
1122 > numbers = ["and a", "two", "three", "four", "five", "six",\r
1123              "seven", "eight", "nine", "ten", "eleven", "twelve"]\r
1124 > printVerse n = do\r
1125       print "On the twelfth day of Christmas, my true love gave to me"\r
1126       for [1..n] (\i -> do\r
1127           c = n-i\r
1128           print $ (if n==1 then "a" else numbers!c) + " " + items!c\r
1129       )\r
1130       print ""\r
1131 > for [1..12] printVerse\r
1132 ...\r
1133 ~~~\r
1134 \r
1135 \r
1136 ----\r
1137 ### Exercise\r
1138 Procude the lyrics of the song ``99 Bottles of Beer''\r
1139 <http://www.99-bottles-of-beer.net/lyrics.html>.\r
1140 \r
1141 \r
1142 ----\r
1143 Sometimes it is useful to introduce a state that can be modified\r
1144 during an algorithm. Such a state is created with function `ref`,\r
1145 it is accessed with `getReg` and modified with `(:=)` operator:\r
1146 ~~~\r
1147 > nRef = ref 1\r
1148 > for [1..8] (\_ -> do \r
1149       n = getRef nRef\r
1150       print n\r
1151       nRef := 2*n\r
1152   )\r
1153 1\r
1154 2\r
1155 4\r
1156 8\r
1157 16\r
1158 32\r
1159 64\r
1160 128\r
1161 ~~~\r
1162 \r
1163 \r
1164 ----\r
1165 ### Exercise\r
1166 Reproduce the `gcd` function by using modifible state.\r
1167 \r
1168 \r
1169 ----\r
1170 This is a partial list of functions in the standard library producing side-effects:\r
1171 \setlength\LTleft{-2cm}\r
1172 <table><tr><td>\r
1173 for </td><td> FunctorE f => f a -> (a -> <e> ()) -> <e> () </td><td> executes the given function with every element in the structure </td></tr><tr><td>\r
1174 print </td><td> Show a => a -> <Proc> () </td><td> prints the given value </td></tr><tr><td>\r
1175 ref </td><td> a -> <Proc> (Ref a) </td><td> creates a state </td></tr><tr><td>\r
1176 getRef </td><td> Ref a -> <Proc> a </td><td> accesses a state </td></tr><tr><td>\r
1177 (:=) </td><td> Ref a -> a -> <Proc> () </td><td> modifies the state </td></tr><tr><td>\r
1178 newArrayList </td><td> () -> <Proc> ArrayList a </td><td> creates an array list </td></tr><tr><td>\r
1179 addArrayList </td><td> ArrayList a -> a -> <Proc> () </td><td> add an element at the end of the list </td></tr><tr><td>\r
1180 getArrayList </td><td> ArrayList a -> Integer -> <Proc> a </td><td> gets an element from the list </td></tr><tr><td>\r
1181 lengthArrayList </td><td> ArrayList a -> <Proc> Integer </td><td> returns the current lenght of the list </td></tr><tr><td>\r
1182 freezeArrayList </td><td> ArrayList a -> <Proc> [a] </td><td> freezes the list and returns the corresponding immutable list\r
1183 </td></tr></table>\r
1184 \r
1185 \r
1186 ## Browsing Simantics database\r
1187 \r
1188 ----\r
1189 The functionality we have used so far has been readily available in the console.\r
1190 There is also functionality that must be imported before using:\r
1191 ~~~\r
1192 > import "Simantics/Ontologies"\r
1193 ~~~\r
1194 The string `Simantics/Ontologies` is the name of the *SCL module* that is imported.\r
1195 We assume that the import command is excuted in the rest of this section. \r
1196 \r
1197 \r
1198 ----\r
1199 In order to browse the database more conveniently, let's define some helper functions.\r
1200 ~~~\r
1201 > nameOfResource r = match possibleRelatedValue r L0.HasName with\r
1202     Just name -> name\r
1203     Nothing -> "no name"\r
1204 > printNames (rs :: [Resource]) = \r
1205       for rs (\r -> print $ nameOfResource r)    \r
1206 > findEntities (p :: Resource -> <ReadGraph> Boolean) = findRecursively\r
1207     where\r
1208       findRecursively r = do \r
1209           children = concatMap findRecursively $ immediateChildren r\r
1210           if p r\r
1211           then [r] + children\r
1212           else children\r
1213       immediateChildren s = s # L0.ConsistsOf     \r
1214 > findByType t = findEntities (flip isInstanceOf t)\r
1215 > aprosOntologies = resource "http://www.apros.fi"\r
1216 > project = currentProject ()\r
1217 ~~~\r
1218 \r
1219 Now we can find all connection types defined in the Apros ontologies:\r
1220 ~~~\r
1221 > printNames $ findByType STR.ConnectionType aprosOntologies\r
1222 PipelineStructureConnectionType\r
1223 ...\r
1224 ElectricalNameReferenceConnectionType\r
1225 ~~~\r
1226 Find all module types:\r
1227 ~~~\r
1228 > import "http://www.apros.fi/Apros-6.1" as APROS\r
1229 > printNames $ findByType APROS.AprosModuleType aprosOntologies\r
1230 ~~~\r
1231 Show all pipes in the workspace with their lengths:\r
1232 ~~~\r
1233 > import "http://www.apros.fi/Combustion/Configuration-6.0/ModuleTypes" \r
1234          as MT\r
1235 > import "http://www.apros.fi/Combustion/Configuration-6.0/Relations" \r
1236          as REL\r
1237 > for (findByType MT.PIPE project) (\pipe ->\r
1238       print $ nameOfResource pipe + " " + \r
1239               show (relatedValue pipe REL.PI12_LENGTH :: Float)      \r
1240   )\r
1241 ~~~\r
1242 Find all modules that are not connected anywhere:\r
1243 ~~~\r
1244 > isUnconnected r = not (existsStatement r STR.IsConnectedTo \r
1245                       || existsStatement r APROS.AttachedModule)\r
1246 > printNames $ filter isUnconnected \r
1247              $ findByType APROS.AprosModule project\r
1248 ~~~\r
1249 \r
1250 \r
1251 ----\r
1252 This is a list of most important database accessing functions (the\r
1253 type `Resource` is abbreviated as `Res` in the type signatures):\r
1254 \setlength\LTleft{-4cm}\r
1255 <table><tr><td>\r
1256 resource </td><td> String -> <ReadGraph> Res </td><td> the resource with the given URI </td></tr><tr><td>\r
1257 uriOf </td><td> Res -> <ReadGraph> String </td><td> the URI of the given resource </td></tr><tr><td>\r
1258 (\#) </td><td> Res -> Res -> <ReadGraph> [Res] </td><td> returns all objects for given subject and predicate </td></tr><tr><td>\r
1259 existsStatement </td><td> Res -> Res -> <ReadGraph> Boolean </td><td> returns true, if there is a statement with the given subject and predicate  </td></tr><tr><td>\r
1260 singleObject </td><td> Res -> Res -> <ReadGraph> Res </td><td> returns the unique object with the given subject and predicate </td></tr><tr><td>\r
1261 possibleObject </td><td> Res -> Res -> <ReadGraph> Maybe Res </td><td> returns a possible object with the given subject and predicate </td></tr><tr><td>\r
1262 valueOf </td><td> Serializable a => Res -> <ReadGraph> a </td><td> reads a value associated with a resource </td></tr><tr><td>\r
1263 relatedValue </td><td> Serializable a => Res -> Res -> <ReadGraph> a </td><td> reads a property </td></tr><tr><td>\r
1264 possibleRelatedValue </td><td> Serializable a => Res -> Res -> <ReadGraph> Maybe a </td><td> reads a possibly existing property </td></tr><tr><td>\r
1265 inverseOf </td><td> Res -> <ReadGraph> Res </td><td> inverse of a relation </td></tr><tr><td>\r
1266 singleTypeOf </td><td> Res -> Res -> <ReadGraph> Res </td><td> the unique type of the resource inheriting the given type </td></tr><tr><td>\r
1267 possibleTypeOf </td><td> Res -> Res -> <ReadGraph> Maybe Res </td><td> a possible type of the resource inheriting the given type </td></tr><tr><td> \r
1268 isInstanceOf </td><td> Res -> Res -> <ReadGraph> Boolean </td><td> tests if a resource is an instance of the given type </td></tr><tr><td>\r
1269 isSubrelationOf </td><td> Res -> Res -> <ReadGraph> Boolean </td><td> tests if a resource is a subrelation of a given relation </td></tr><tr><td>\r
1270 isInheritedFrom </td><td> Res -> Res -> <ReadGraph> Boolean </td><td> tests if a resource is a subtype of a given type </td></tr><tr><td>\r
1271 claim </td><td> Res -> Res -> Res -> <WriteGraph> () </td><td> adds a statement </td></tr><tr><td>\r
1272 deny </td><td> Res -> Res -> Res -> <WriteGraph> () </td><td> removes a statement </td></tr><tr><td>\r
1273 claimRelatedValue </td><td> Serializable a => Res -> Res -> a -> <WriteGraph> () </td><td> sets the value of a property </td></tr><tr><td>\r
1274 syncRead </td><td> (() -> <Proc,ReadGraph> a) -> <Proc> a </td><td> makes a read request </td></tr><tr><td>\r
1275 syncWrite </td><td> (() -> <Proc,ReadGraph,WriteGraph> a) -> <Proc> a </td><td> makes a write request\r
1276 </td></tr></table>\r
1277 \r
1278 \r
1279 ## Manipulating diagrams\r
1280 \r
1281 ----\r
1282 Diagrams could be in principle manipulated with the set of primitive\r
1283 graph functions introduced in the previous section. There is however\r
1284 some tools available to work with diagrams at a higher level. \r
1285 Therefore we need for this section the following imports:\r
1286 ~~~\r
1287 > import "Simantics/Diagram"\r
1288 > import "http://www.apros.fi/Apros-6.1" as APROS\r
1289 > import "http://www.apros.fi/Combustion/Configuration-6.0/Relations" \r
1290          as REL\r
1291 > import "http://www.apros.fi/Combustion/Diagram-6.0/Symbols" \r
1292          as SYMBOLS          \r
1293 > import "http://www.apros.fi/Combustion/Diagram-6.0/Relations" \r
1294          as CPS\r
1295 ~~~\r
1296 \r
1297 For this section you should also create a model with (default) name Model\r
1298 and a new diagram to that model with (default) name NewGenericDiagram. If\r
1299 you want to change these names, you should also change the code\r
1300 examples accordingly. Populate the diagram with couple of elements and\r
1301 connect them together.\r
1302 \r
1303 \r
1304 ----\r
1305 We show first how to read the diagram contents:\r
1306 ~~~\r
1307 > dia = diagram (model "Model") ["NewGenericDiagram"]\r
1308 > for (elementsOfR dia) print\r
1309 (Connection [Terminal "SP_01" #221240, Terminal "MU_01" #218187] [Edge 0 1] (Just "XA_02"), #450761)\r
1310 (Component #217233 "SP_01" (Position ...) [Property #137577, ...], #450756)\r
1311 (Component #217663 "MU_01" (Position ...) [Property #144599, ...], #450751)\r
1312 ~~~\r
1313 The actual result depends on how you have populated your diagram.\r
1314 \r
1315 The result is not very readable because of all the resource identifiers. \r
1316 Let's write a pretty-printing function:\r
1317 ~~~\r
1318 > printElement ((Component t n pos props),_) = do\r
1319     print $ n + " :: " + nameOfResource t\r
1320     print $ "    " + show pos\r
1321     for props (\(Property relation value) ->\r
1322         print $ "    " + nameOfResource relation + " " + show value\r
1323     )\r
1324  printElement ((Connection nodes _ name),_) = do\r
1325     print $ "Connection " + \r
1326             (match name with Just n -> n ; Nothing -> "")\r
1327     printNode (Terminal element connectionPoint) = \r
1328         print $ "    " + element + " " + nameOfResource connectionPoint\r
1329     printNode otherwise = ()\r
1330     for nodes printNode\r
1331  printElement ((Flag t name _ _ _ _ _ pos _),_) = do\r
1332     print $ "Flag " + name + " :: " + nameOfResource t\r
1333     print $ "    " + show pos\r
1334  printElement (el,_) = print el // Use the default printing as a fallback \r
1335 ~~~\r
1336 Now we get:\r
1337 ~~~>  \r
1338 > for (elementsOfR dia) printElement\r
1339 Connection XA_02\r
1340     SP_01 SP_OUTPUT_SIGN_1_1\r
1341     MU_01 MULTIPLYER_INPUT_SIGN_1_1\r
1342 SP_01 :: SetpointS\r
1343     Position 1.0 0.0 0.0 1.0 94.0 115.0\r
1344     SP_VALUE 0.0\r
1345     SP_MINMAX_ON false\r
1346     SP_GRADIENT_UP 60.0\r
1347     SP_TRACKING_ON false\r
1348     SP_MIN 0.0\r
1349     SP_GRADIENT_DOWN -60.0\r
1350     SP_FAST_MODE_ON true\r
1351     SP_MAX 100.0\r
1352 MU_01 :: Gain\r
1353     Position 1.0 0.0 0.0 1.0 104.0 115.0\r
1354     MULTIPLYER_BIAS 0.0\r
1355     MULTIPLYER_GAIN 1.0\r
1356     MULTIPLYER_OUTPUT 0.0\r
1357 ~~~\r
1358 \r
1359 \r
1360 ----\r
1361 Next, let's create some new diagrams. We need two helper functions:\r
1362 ~~~\r
1363 > aprosDiagram modelName diagramName = NewDiagram \r
1364       (model modelName) \r
1365       [diagramName]\r
1366       APROS.Folder\r
1367       APROS.GenericAprosComposite\r
1368 > joinMap = createJoinMap ()\r
1369 ~~~\r
1370 The first function creates a specification for a new diagram:\r
1371 it describes the model where the diagram is created, the path\r
1372 to the diagram, the type of folders in the path and finally\r
1373 the type of the diagram itself. The second definition defines\r
1374 a `joinMap` that is used for connecting diagrams together (by flags).\r
1375 \r
1376 Now we can write:\r
1377 ~~~\r
1378 > newDia = fst $ createDiagramR (aprosDiagram "Model" "TestDiagram1") joinMap []\r
1379 ~~~\r
1380 This should create a new diagram with name TestDiagram1. The\r
1381 last parameter is the list of diagram elements. Because the list\r
1382 is empty, our diagram is also empty.\r
1383 \r
1384 Easiest way to create some content is to copy it from another diagram:\r
1385 ~~~\r
1386 > sortEls l = filter (not . isReferring) l + filter isReferring l\r
1387     where\r
1388       isReferring (Connection _ _ _) = True\r
1389       isReferring (SimpleConnection _ _ _ _ _) = True\r
1390       isReferring (Monitor _ _ _ _) = True\r
1391       isReferring otherwise = False\r
1392 > els = sortEls $ map fst $ elementsOfR dia\r
1393 > createDiagramR (ExistingDiagram newDia) joinMap els \r
1394 ~~~\r
1395 This replaces the contents of TestDiagram1 by the contents of NewGenericDiagram.\r
1396 The function `sortEls` is needed to work around a bug in `createDiagramR`\r
1397 occurring if some element is created after another element that refers to it.\r
1398 \r
1399 \r
1400 ----\r
1401 Usually we want to modify the contents of the diagram somehow before copying it.\r
1402 Here are couple of example functions for transforming the elements:\r
1403 ~~~\r
1404 > mapElementName f (Component t name pos props) =\r
1405       Component t (f name) pos props\r
1406   mapElementName f (Connection nodes edges possibleName) =\r
1407       Connection (map prefixNode nodes) edges (map f possibleName)\r
1408     where\r
1409       prefixNode (Terminal name cp) = Terminal (f name) cp\r
1410       prefixNode n = n\r
1411   mapElementName f (Flag t name label output external \r
1412                          ioBinding ioTableRowIndex pos refs) = \r
1413       Flag t (f name) label output external \r
1414            ioBinding ioTableRowIndex pos refs\r
1415   mapElementName f el = el // This is not yet a complete definition!\r
1416 > moveElement delta (Component t name pos props) =\r
1417       Component t name (move delta pos) props\r
1418   moveElement delta (Connection nodes edges name) =\r
1419       Connection (map moveNode nodes) edges name\r
1420     where\r
1421       moveNode (RouteLine False pos) = RouteLine False (pos + fst delta)\r
1422       moveNode (RouteLine True pos) = RouteLine True (pos + snd delta)\r
1423       moveNode n = n\r
1424   moveElement delta (Flag t name label output external\r
1425                           ioBinding ioTableRowIndex pos refs) = \r
1426       Flag t name label output external \r
1427            ioBinding ioTableRowIndex (move delta pos) refs\r
1428   moveElement delta el = el // This is not yet a complete definition!\r
1429 ~~~\r
1430 Now we can move the elements and add a prefix to them:  \r
1431 ~~~  \r
1432 > modifiedEls = map (moveElement (20,20)) \r
1433               $ map (mapElementName ((+) "PREFIX_")) els\r
1434 > createDiagramR (ExistingDiagram newDia) joinMap modifiedEls\r
1435 ~~~\r
1436 \r
1437 Finally, let's try making some clones of the elements:\r
1438 ~~~  \r
1439 > modifiedEls = [ moveElement (dx,dy) $ mapElementName ((+) prefix) el\r
1440                 | i <- [0..3]\r
1441                 , j <- [0..3]\r
1442                 , dx = 30 * fromInteger i\r
1443                 , dy = 30 * fromInteger j\r
1444                 , prefix = "P_" + show i + "_" + show j + "_"\r
1445                 , el <- els] \r
1446 > createDiagramR (ExistingDiagram newDia) joinMap modifiedEls\r
1447 ~~~\r
1448 \r
1449 \r
1450 ----\r
1451 ### Exercise\r
1452 Write a function `createPipeline` that takes as a parameter\r
1453 a diagram specification and a list of two-dimensional points\r
1454 and creates a pipeline such that elevations of the points are\r
1455 the second components of the points in the list, the lengths \r
1456 of the points are the distances between successive points and\r
1457 the diagram positions are based on the physical positions.\r
1458 The following command should work: \r
1459 ~~~\r
1460 > dia = ExistingDiagram (diagram (model "Model") ["TestDiagram1"])\r
1461 > createPipeline dia [(1,1), (6,1), (10,5)]\r
1462 ~~~\r
1463 \r
1464 Hint: The following commands create a pipe and a point that are connected\r
1465 together with point elevation and pipe lenght specified:   \r
1466 ~~~\r
1467 > els = [\r
1468       Component SYMBOLS.Point "PO_01" (location 30 30) \r
1469                 [Property REL.PO11_ELEV (toDynamic 10.0)],\r
1470       Component SYMBOLS.Pipe "PI_01" (location 40 30) \r
1471                 [Property REL.PI12_LENGTH (toDynamic 5.0)],\r
1472       Connection [Terminal "PO_01" CPS.PointSelf,\r
1473                   Terminal "PI_01" CPS.PI12_CONNECT_POINT_1_1_1]\r
1474                   [Edge 0 1] Nothing\r
1475   ]\r
1476 > createDiagramR dia joinMap els\r
1477 ~~~\r
1478 \r
1479 \r
1480 ----\r
1481 ### Remark\r
1482 This is the data type definition of the diagram elements:\r
1483 ~~~\r
1484 data DiagramElement res = \r
1485     Component\r
1486         res            // component type\r
1487         String         // name\r
1488         Position       // position\r
1489         [Property res] // properties\r
1490   | SimpleConnection String res String res (Maybe String)\r
1491   | Connection [ConnectionNode res] [Edge] (Maybe String)\r
1492   | Flag \r
1493         res \r
1494         String         // name \r
1495         String         // label\r
1496         Boolean        // output\r
1497         Boolean        // external\r
1498         (Maybe String)  // IOTableBinding\r
1499         (Maybe Integer) // IOTableRowIndex\r
1500         Position       // position  \r
1501         [Dynamic]      // references to the joins\r
1502   | SVG String Position\r
1503   | Monitor String (Maybe MonitorReference) MonitorVisuals Position\r
1504 data Position = Position Double Double Double Double Double Double\r
1505 data Property res = Property res Dynamic\r
1506 data Edge = Edge Integer Integer\r
1507 data ConnectionNode res = Terminal String res\r
1508                         | RouteLine\r
1509                               Boolean   // is horizontal\r
1510                               Double    // position\r
1511 data Font = Font String Integer Integer\r
1512 data Alignment = Baseline | Center\r
1513                | Leading | Trailing\r
1514 data MonitorReference = MonitorReference String String\r
1515 data MonitorVisuals = MonitorVisuals (Maybe Font) Double Alignment Alignment                              \r
1516 ~~~\r
1517 \r
1518 ## Model queries\r
1519 \r
1520 ----\r
1521 In this section, we make queries and mass modifications to the components\r
1522 of a model. For preliminaries, you need to run the import command:\r
1523 ~~~\r
1524 import "Apros/ModelQueries"\r
1525 ~~~\r
1526 \r
1527 It defines the following functions:\r
1528 ~~~\r
1529 forAllComponentsIn :: (Resource -> <e> a) -> Resource -> <ReadGraph,e> ()\r
1530 forAllComponents ::  (Resource -> <e> a) -> <Proc,ReadGraph,e> ()\r
1531 forComponentsIn :: (Resource -> <e> Boolean) -> Resource \r
1532                 -> (Resource -> <e> a) -> <ReadGraph,e> ()\r
1533 forComponents :: (Resource -> <e> Boolean) -> (Resource -> <e> a) -> <Proc,ReadGraph,e> ()\r
1534 searchComponents :: (Resource -> <e> Boolean) -> <Proc,ReadGraph,e> [Resource]\r
1535 searchComponentsIn :: (Resource -> <e> Boolean) -> Resource -> <ReadGraph,e> [Resource]\r
1536 \r
1537 nameSatisfies :: (String -> <e> Boolean) -> Resource -> <e,ReadGraph> Boolean\r
1538 nameIs name = nameSatisfies (== name)\r
1539 getName :: Resource -> <ReadGraph> String\r
1540 \r
1541 typeIs :: Resource -> Resource -> <ReadGraph> Boolean\r
1542 \r
1543 configurationValueSatisfies :: Serializable a => Resource -> (a -> <e> Boolean) \r
1544                             -> Resource -> <e,ReadGraph> Boolean\r
1545 configurationValueIs :: Serializable a => Resource -> a \r
1546                      -> Resource -> <e,ReadGraph> Boolean\r
1547 setConfigurationValue :: Serializable a => Resource -> a -> Resource -> <WriteGraph> ()\r
1548 getConfigurationValue :: Serializable a => Resource -> Resource -> <ReadGraph> a\r
1549 \r
1550 stateValueSatisfies :: Serializable a => Resource -> (a -> <e> Boolean) \r
1551                     -> <ReadGraph> (Resource -> <e,ReadGraph> Boolean)\r
1552 stateValueIs :: Serializable a => Resource -> a \r
1553              -> <ReadGraph> (Resource -> <e,ReadGraph> Boolean)\r
1554 setStateValue :: Serializable a => Resource -> a\r
1555               -> <ReadGraph> (Resource -> <WriteGraph> ())\r
1556 getStateValue :: Serializable a => Resource -> <ReadGraph> (Resource -> <ReadGraph> a)\r
1557 \r
1558 (&&&) :: Combinable a => a -> a -> a\r
1559 instance Combinable (Resource -> <e> Boolean)\r
1560 instance Combinable (Resource -> <e> ())\r
1561 \r
1562 printName :: Resource -> <ReadGraph,Proc> ()\r
1563 row :: [Resource -> <e> String] -> (Resource -> <e> String)\r
1564 ~~~\r
1565 \r
1566 \r
1567 ----\r
1568 The functions make it possible to define queries to the active\r
1569 model of the form:\r
1570 ``for all components satisfying a condition execute an action.''\r
1571 For example:\r
1572 \r
1573 1) Print the names of all points in the model:\r
1574     ~~~\r
1575    forComponents\r
1576        (typeIs MODULETYPES.POINT)\r
1577        printName\r
1578    ~~~ \r
1579 2) Set area of pipe PIP01 to 0.0033\r
1580    ~~~\r
1581    forComponents\r
1582        (nameIs "PIP01")\r
1583        (setConfigurationValue ATTRIBUTES.PI12_AREA 0.2)\r
1584    ~~~\r
1585 3) Find all pipes in the active model and set their area to 0.001 m2:\r
1586    ~~~\r
1587    forComponents\r
1588        (typeIs MODULETYPES.PIPE)\r
1589        (setConfigurationValue ATTRIBUTES.PI12_AREA (0.001 :: Float))\r
1590    ~~~\r
1591 4) Find all pipes with area < 0.0001 m2 in the active model and set their area to 0.001 m2:\r
1592    ~~~\r
1593    forComponents\r
1594        (configurationValueSatisfies ATTRIBUTES.PI12_AREA (\(x :: Float) -> x < 0.0001))\r
1595        (setConfigurationValue ATTRIBUTES.PI12_AREA (0.001 :: Float))\r
1596    ~~~\r
1597 5) Find all pipes with fluid section WSB and list their boron concentrations:\r
1598    ~~~\r
1599    forComponents\r
1600        (configurationValueIs ATTRIBUTES.PO11_SECTION_NAME "WSB")\r
1601        (print . row [getName, showFloat . getStateValue ATTRIBUTES.PO11_BOR_CONC])\r
1602    ~~~\r
1603 6) Find all pipes with fluid section WS and set their fluid section to WSB:\r
1604    ~~~\r
1605    forComponents\r
1606        (configurationValueIs ATTRIBUTES.PO11_SECTION_NAME "WS")\r
1607        (setConfigurationValue ATTRIBUTES.PO11_SECTION_NAME "WSB")\r
1608    ~~~\r
1609 7) Find all pipes in diagram Diagram2 and set their length to 123.45 m:\r
1610    ~~~\r
1611    forComponentsIn\r
1612          (typeIs MODULETYPES.PIPE)\r
1613          (resource "http://Projects/Development%20Project/Model/Configuration/Diagram2")\r
1614          (setConfigurationValue ATTRIBUTES.PI12_LENGTH (123.45 :: Float))\r
1615    ~~~  \r
1616 \r
1617 ----\r
1618 It is also possible to write the results of a query to a file.\r
1619 ~~~\r
1620 printingToFile "c:/temp/componentListing.txt" (\r
1621     forComponents\r
1622         (configurationValueIs ATTRIBUTES.PO11_SECTION_NAME "WSB")\r
1623         (print . row [getName, showFloat . getStateValue ATTRIBUTES.PO11_BOR_CONC])\r
1624     )\r
1625 ~~~\r
1626 \r
1627 \r
1628 # Further topics\r
1629 \r
1630 ----\r
1631 \r
1632 If you start to use SCL more frequently and write your own helper functions,\r
1633 it becomes quickly cumbersome to paste them every time into the console.\r
1634 You can write a list of commands into a separate file and run it with the command\r
1635 ~~~\r
1636 > runFromFile "c:/file/path"\r
1637 ~~~\r
1638 Commands are separated from each other by indentation.\r
1639 \r
1640 Another way to store function definitions is to write your own modules.\r
1641 It also frees you from some restrinctions of SCL Console.\r
1642 You can write the module into a file, say `c:/scl/MyModule.scl`\r
1643 and import it as:\r
1644 ~~~\r
1645 > import "file:c:/scl/MyModule"\r
1646 ~~~\r
1647 What makes working with modules harder than console commands is that\r
1648 it is not so easy to update a module that you have already imported.\r
1649 It is however possible by running:\r
1650 ~~~\r
1651 > reset ""\r
1652 ~~~\r
1653 that clears the whole SCL environment. After clearing the environment, you \r
1654 have to reimport all the modules you want to use.\r
1655 We will improve the situation in next versions of \r
1656 the SCL environment.\r
1657 \r
1658 \r
1659 ----\r
1660 There are many language features we have not touched in this tutorial.\r
1661 Many of them are also in Haskell, so you can familize yourself with them\r
1662 by reading Haskell tutorials:\r
1663 * defining new data types,\r
1664 * defining new type classes and their instances,\r
1665 * defining binary operators, their associativity and precedence.\r
1666 SCL supports also monads like Haskell. Only difference is that monadic\r
1667 syntax uses keyword `mdo` instead of `do`. Althought\r
1668 the importance of monads is lessen in SCL because of effect types,\r
1669 they are still a useful concept to know. Monads are particularly\r
1670 useful for building domain specific languages in SCL.\r
1671 \r
1672 \r
1673 ----\r
1674 There are also couple of features that we have not described that\r
1675 are specific to SCL:\r
1676 * definition of new effect types\r
1677 * syntax for importing Java code to SCL, for example:\r
1678   ~~~\r
1679   importJava "java.util.List" where\r
1680       @JavaName get\r
1681       (!) :: [a] -> Integer -> a\r
1682   \r
1683       @JavaName size\r
1684       length :: [a] -> Integer\r
1685   \r
1686       subList :: [a] -> Integer -> Integer -> [a]\r
1687   ~~~\r
1688 * value annotations\r
1689   ~~~\r
1690   @inline\r
1691   curry :: ((a, b) -> <e> c) -> a -> b -> <e> c\r
1692   curry f x y =  f (x, y)\r
1693   \r
1694   @macro\r
1695   a && b = if a then b else False\r
1696   ~~~\r
1697 \r
1698 \r