]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "Fix to OrderedSetTemplate, preference for autocompletion"
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Mon, 1 Oct 2018 10:44:28 +0000 (10:44 +0000)
committerGerrit Code Review <gerrit2@simantics>
Mon, 1 Oct 2018 10:44:28 +0000 (10:44 +0000)
36 files changed:
bundles/org.simantics.scl.tutorial/.classpath [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/.project [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/build.properties [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.01 Console.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.02 Language basics.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.03 Evaluation semantics.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.04 Numbers.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.05 Lists.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.06 Types.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.07 Booleans.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.08 Side effects.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.09 Strings.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.10 Optional values (Maybe).md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.11 Functions.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/1.12 Tuples.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/2.02 Model configuration.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/2.03 (Exercise) Pipelines.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/2.04 (Exercise) Polyline.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/2.05 Semantic graph.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/2.06 (Exercise) Pipelines again.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/2.07 (Solution) Pipelines.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/2.08 (Solution) Polyline.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/2.09 (Solution) Pipelines again.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/3.01 Simulation sequences.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/3.02 (Exercise) Model fitting.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/3.03 (Exercise) Controller tuning.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/3.04 (Solution) Model fitting.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/4.01 Other language features.md [new file with mode: 0644]
bundles/org.simantics.scl.tutorial/scl/Tutorial/X Old tutorial.md [new file with mode: 0644]
bundles/org.simantics.selectionview.ontology/graph/Selectionview.pgraph
bundles/org.simantics.selectionview/src/org/simantics/selectionview/DisplayValueVariableAdapter.java
bundles/org.simantics.selectionview/src/org/simantics/selectionview/function/All.java
bundles/pom.xml
features/org.simantics.sdk.feature/feature.xml

diff --git a/bundles/org.simantics.scl.tutorial/.classpath b/bundles/org.simantics.scl.tutorial/.classpath
new file mode 100644 (file)
index 0000000..b1dabee
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/bundles/org.simantics.scl.tutorial/.project b/bundles/org.simantics.scl.tutorial/.project
new file mode 100644 (file)
index 0000000..16f19de
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.scl.tutorial</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/bundles/org.simantics.scl.tutorial/.settings/org.eclipse.jdt.core.prefs b/bundles/org.simantics.scl.tutorial/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..11f6e46
--- /dev/null
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7\r
+org.eclipse.jdt.core.compiler.compliance=1.7\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.7\r
diff --git a/bundles/org.simantics.scl.tutorial/META-INF/MANIFEST.MF b/bundles/org.simantics.scl.tutorial/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..f1c8713
--- /dev/null
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Tutorial
+Bundle-SymbolicName: org.simantics.scl.tutorial
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
diff --git a/bundles/org.simantics.scl.tutorial/build.properties b/bundles/org.simantics.scl.tutorial/build.properties
new file mode 100644 (file)
index 0000000..0a70903
--- /dev/null
@@ -0,0 +1,6 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .,\\r
+               scl/\r
+src.includes = scl/\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.01 Console.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.01 Console.md
new file mode 100644 (file)
index 0000000..011db66
--- /dev/null
@@ -0,0 +1,73 @@
+# Console\r
+\r
+The easiest way of getting started with SCL is to use SCL console that is normally included in\r
+Simantics-based products. You can open the console by pressing ALT-SHIFT-q and s or\r
+from menu **Window/Show View/SCL Console**.\r
+\r
+## Executing commands \r
+\r
+SCL console works by executing commands you write into the input box in the bottom of the view.\r
+After the command has been written, it can be executed by pressing ENTER. If the command\r
+contains syntax errors they are written to the console in red text and indication for the\r
+error position.\r
+\r
+Multi-line commands can be written by creating a new line with CTRL-ENTER. \r
+The command history can be browsed with CTRL-UP and CTRL-DOWN.\r
+Also the standard keybindings CTRL-c (Copy), CTRL-v (Paste), CTRL-x (Cut), CTRL-a (Select all) work as expected\r
+both in the input and output area of the console depending on which of them has a focus.\r
+You can also write (or paste) multiple commands at the same time.\r
+\r
+If the command you write into console results as an ordinary value, it is printed\r
+to the console. Here are couple of examples you can try:\r
+\r
+~~~\r
+> 13\r
+13\r
+> 1+2\r
+3\r
+> sin 1\r
+0.8414709848078965\r
+> "Hello " + "world!"\r
+Hello world!\r
+> [1,3,5]\r
+[1, 3, 5]\r
+~~~\r
+\r
+The console remembers the variables you declare, but they are forgotten when the\r
+console (or the whole application) is closed.\r
+\r
+~~~\r
+> x = 35\r
+> y = 40\r
+> x + y\r
+75\r
+> x * y\r
+1400\r
+~~~\r
+\r
+If you write a command that prints something as a side-effect, the prints are shown in the console:\r
+\r
+~~~\r
+> print "Hello" ; print "world!"\r
+Hello\r
+world!\r
+~~~\r
+\r
+The currently running command can be interrupted with **Interrupt current command** button\r
+in the top right corner of the console.\r
+All commands don't support interruption.\r
+The output area of the console can be cleared with **Clear console** button.\r
+\r
+## Importing modules\r
+\r
+The rightmost button in the console opens a dialog for managing modules that are available\r
+for the console. It shows currently imported modules and contains buttons for importing\r
+modules from different sources. The imported modules are remembered even when the console\r
+is closed if the import is marked persistent. \r
+\r
+The another way to import modules is run import command from the console, for example\r
+\r
+    import "Simantics/DB"\r
+\r
+The button with two arrows reloads the modules that are imported to the console. It\r
+is useful if you develop your own module and want to test modified definitions.
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.02 Language basics.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.02 Language basics.md
new file mode 100644 (file)
index 0000000..82e575c
--- /dev/null
@@ -0,0 +1,357 @@
+# Language basics\r
+\r
+SCL is a functional programming language that is based on [lambda calculus]. \r
+Lambda calculus is a minimal but still Turing complete language with three\r
+constructions:\r
+* *Variables*\r
+* *Function applications*\r
+* *Function definitions* (lambda terms)\r
+\r
+These are also the most central elements of SCL and most of the other constructions are only\r
+syntactic sugar on top of lambda calculus.\r
+\r
+SCL syntax is very close to the syntax of [Haskell] programming language and many tutorials\r
+on Haskell apply also to SCL. The main difference between the languages is the evaluation strategy:\r
+Haskell evaluates terms lazily, SCL strictly. Unlike Haskell, SCL allows side-effects during\r
+function application, but controls them with effect typing. In this respects, it behaves similarly\r
+to [ML] or [OCaml].\r
+\r
+SCL inherits the following philosophy from Haskell and other programming languages in functional paradigm: \r
+* Avoid stateful programming \r
+* Express mathematical problems in mathematical syntax\r
+* Expressive types prevent runtime errors\r
+\r
+[lambda calculus]: http://en.wikipedia.org/wiki/Lambda_calculus\r
+[Haskell]: https://www.haskell.org/\r
+[ML]: http://en.wikipedia.org/wiki/ML_(programming_language)\r
+[OCaml]: https://ocaml.org/\r
+\r
+This section gives a walkthrough for the most importatant constructs of SCL language.\r
+\r
+## Literals\r
+\r
+SCL supports the following types of constant expressions: \r
+\r
+**Integers**\r
+\r
+    3423\r
+    \r
+**Floating point numbers**\r
+    \r
+    1.2\r
+    2.6e-4\r
+    \r
+**String literals**\r
+\r
+SCL supports single-line strings (enclosed in quotes) \r
+\r
+    "Single line text"\r
+    "Text\nwith\nmultiple lines"\r
+\r
+and multi-line strings (enclosed in triple quotes)\r
+\r
+    """Text\r
+    with\r
+    multiple lines"""\r
+\r
+Single-line strings may contain escaped characters (`\n` line feed, `\t` tabulator, `\r` carriage return, `\uxxxx` unicode character,\r
+`\<character>` the character without the first `\`).\r
+    \r
+**Character literals**\r
+\r
+    't'\r
+    '\''\r
+    \r
+**Boolean constants** are written as `True` and `False` although they are not technically literals (but constructors).\r
+\r
+## Identifiers\r
+\r
+Variable and constant names start with lower case letter followed by letters, digits, `_` and `'`.\r
+It customary to write multi-word concepts with camel case convention, for example\r
+`printError` or `importA5Model`.\r
+\r
+The following names are reserved and cannot be used as identifiers:\r
+`as`, `by`, `class`, `data`, `deriving`, `do`, `effect`, `else`, `enforce`, `extends`, `forall`, `hiding`, `if`,\r
+`import`, `importJava`, `in`, `include`, `infix`, `infixl`, `infixr`, `instance`, `let`, `match`, `mdo`, `rule`,\r
+`select`, `then`, `transformation`, `type`, `when`, `where`, `with`.\r
+\r
+Identifiers starting with upper case letter are *constructors* and they can be defined only\r
+together with the new data types. Examples: `True`, `False` and `Nothing`.\r
+\r
+## Function applications\r
+\r
+A function is applied by writing the function and its parameters consecutively.\r
+\r
+    sin pi\r
+    max 2 5\r
+\r
+A parameter needs to be closed in parenthesis if it is not a variable, literal, or an expression starting\r
+with `if`, `let`, `do`, etc. \r
+\r
+    sqrt (x*x + y*y)\r
+    atan2 (sin a) (cos a)\r
+\r
+For example\r
+\r
+    sqrt x*x + y*y\r
+    \r
+is evaluated as\r
+\r
+    (sqrt x)*x + y*y\r
+\r
+because the function application has higher precedence than\r
+any binary operator.\r
+Parentheses are also needed around negation\r
+\r
+    sin (-1.42)\r
+\r
+because otherwise the expression is tried to compile as\r
+\r
+    sin - 1.42\r
+\r
+causing a compilation error because `sin` and `1.42` are not\r
+compatible for subtraction.\r
+\r
+## Binary operators\r
+\r
+Binary operators are normal functions that are just written between their parameters:\r
+\r
+    1 + 2\r
+\r
+Each binary operator can be converted into ordinary function by putting parentheses around it\r
+\r
+    (+) 1 2\r
+\r
+Similarly an ordinary function can be converted into binary operator by putting backticks (\`) around it.\r
+\r
+    3.4 `max` 4.5\r
+    \r
+Binary operators have precedences that determines how multiple consecutive binary operators\r
+are compiled. For example\r
+\r
+    1*2+3*4+5*6\r
+   \r
+is evaluated as\r
+\r
+    ((1*2) + (3*4)) + (5*6)\r
+\r
+## Variable definitions\r
+\r
+Variables are defined by syntax\r
+\r
+    variableName = variableValue\r
+\r
+for example\r
+\r
+    g = 9.80665\r
+\r
+Defined variable values are available in the\r
+consecutive expressions:\r
+\r
+    a = 13\r
+    b = 14\r
+    a*b\r
+\r
+## Function definitions\r
+\r
+Functions are defined by writing a function application\r
+in the left-hand side of the equation:\r
+\r
+    increaseByOne x = x+1\r
+    \r
+Defined functions are available in the consecutive expressions:\r
+\r
+    increaseByOne 13\r
+\r
+## Conditional expressions\r
+\r
+Conditional expressions are written in the form:\r
+\r
+    if <condition> then <successBranch> else <failureBranch>\r
+    \r
+The `else` branch is always mandatory.\r
+\r
+    abs x = if x > 0\r
+            then x\r
+            else -x\r
+\r
+## Recursion\r
+\r
+A function definition can refer to itself. For example, the Euclidean algorithm for\r
+computing the greatest common divisor of two integers can be written as:\r
+\r
+    gcd a b = if a > b\r
+              then gcd b a\r
+              else if a == 0\r
+              then b\r
+              else gcd (b `mod` a) a\r
+\r
+## Local definitions\r
+\r
+Variable and function definitions can be written as a part of larger\r
+expression. There are three language constructs for this purpose:\r
+\r
+    let <definitions> in <result>\r
+    \r
+    do <definitions> \r
+       <result>\r
+       \r
+    <definition> where <definitions>\r
+\r
+They are quite similar and\r
+it is usually just a stylistic choice which one to use.\r
+\r
+If you are only defining local variables that are needed in a subexpression\r
+and their computation does not have side-effects (or has only reading effects),\r
+the most natural choice is `let`-construct that allows you to define\r
+variables between `let` and `in` and used the variables in the expression following `in`:\r
+\r
+~~~\r
+distance (x1,y1) (x2,y2) = let dx = x1-x2\r
+                               dy = y1-y2\r
+                           in sqrt (dx*dx + dy*dy) \r
+~~~\r
+\r
+Let-expressions can be freely embedded in other expressions:\r
+\r
+~~~\r
+"""\r
+Finds a root of f given neg and pos with assumption that\r
+   f neg < 0\r
+and\r
+   f pos > 0 \r
+""" \r
+bisectionMethod f neg pos =\r
+  let middle = (neg+pos)*0.5 in\r
+    if abs (neg-pos) < 1e-9\r
+    then middle\r
+    else let middleVal = f middle in\r
+      if middleVal < (-1e-9)\r
+      then bisectionMethod f middle pos\r
+      else if middleVal > 1e-9\r
+      then bisectionMethod f neg middle\r
+      else middle\r
+~~~\r
+\r
+Another construction allowing local variable bindings is `do`. The value of the whole\r
+`do`-expression is determined by the last expression in the `do`-block. This construct\r
+should be used when there are side-effects involved and you want to mix variable bindings\r
+with function applications that ignore their result:\r
+\r
+~~~\r
+createModel parent name = do\r
+    model = newResource ()\r
+    claim model L0.InstanceOf SIMU.Model\r
+    claimRelatedValue model L0.HasName name\r
+    claim model L0.PartOf parent\r
+    model\r
+~~~\r
+\r
+The final binding construction is `where` that locates variable definitions after the position the variables are used. It differs from `let` and `do` because\r
+it does not define an expression but is always related to some other definition.\r
+The benefit is that the same `where` -block can be used by multiple\r
+different guarded definitions:  \r
+\r
+~~~\r
+"""\r
+Returns all solutions of the quadratic equation a*x^2 + b*x + c = 0.\r
+"""\r
+solveQuadratic :: Double -> Double -> Double -> [Double]\r
+solveQuadratic a b c\r
+    | discriminant < 0 = []\r
+    | discriminant > 0 = let sqrtDisc = sqrt discriminant\r
+                         in [ (-b-sqrtDisc)/(2*a)\r
+                            , (-b+sqrtDisc)/(2*a) ]\r
+    | otherwise        = [ -b / (2*a) ]\r
+  where\r
+    discriminant = b*b - 4*a*c\r
+~~~\r
+\r
+\r
+## Functions taking other functions as parameters\r
+\r
+In SCL, functions are ordinary values that can be stored to variables and manipulated.\r
+For example, writing only the function name to the console produces:\r
+\r
+    > sin\r
+    <value of type Double -> <a> Double> \r
+\r
+We can define for example a numerical derivative operation\r
+\r
+    epsilon = 1e-9\r
+    der f x = (f (x + epsilon) - f (x - epsilon)) / (2*epsilon)\r
+    \r
+Now,\r
+    \r
+    > der sin 0\r
+    1.0\r
+    > der exp 1\r
+    2.7182818218562943\r
+\r
+## Anonymous function definitions\r
+\r
+Functional style of programming favors lots of small functions.\r
+Giving a name for all of them becomes quickly tedious and\r
+therefore functions can be defined also anonymously. For\r
+example \r
+\r
+    \x -> x+1\r
+\r
+defines a function that increases its parameter by one.\r
+Thus\r
+\r
+    (\x -> x+1) 13\r
+    \r
+returns `14`.\r
+\r
+Assuming that the function `der` is defined as above\r
+\r
+    > der (\x -> x*x) 2\r
+    4.000000330961484 \r
+\r
+## Partial function application\r
+\r
+It is possible to give a function less parameters that\r
+it accepts:\r
+\r
+    > der sin\r
+    <value of type Double -> <a> Double>\r
+    \r
+Such a partial application creates a function that expects\r
+the missing parameters:\r
+\r
+    > myCos = der sin\r
+    > myCos 0\r
+    > myCos pi\r
+    -1.000000082740371\r
+\r
+It is possible to partially apply also binary operators giving\r
+only one of its parameters. Such an application must always\r
+be enclosed in parentheses\r
+    \r
+    lessThanOne = (< 1)\r
+    greaterThanOne = (1 <)\r
+\r
+## Pattern matching\r
+\r
+The constructors are special kind of values and functions\r
+that can be used in the left-hand side of the function and\r
+value definitions. Most common constructors are\r
+the tuple constructors `()`, `(,)`, `(,,)`, ...:  \r
+\r
+    toPolarCoordinates (x,y) = (sqrt (x*x + y*y), atan2 y x)\r
+    toRectangularCoordinates (r,angle) = (r*cos angle, r*sin angle)\r
+\r
+Other constructors are used like functions, but the name\r
+of the constructor is capitalized, for example `Just` and `Nothing`:\r
+\r
+    fromMaybe _       (Just v) = v\r
+    fromMaybe default Nothing  = default\r
+    \r
+This example demonstrates also some other features. A function \r
+can be defined with multiple equations and the first matching\r
+equation is used. Also, if some parameter value is not used,\r
+it may be replaced by `_`.\r
+\r
+## Indentation\r
+\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.03 Evaluation semantics.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.03 Evaluation semantics.md
new file mode 100644 (file)
index 0000000..5c9007f
--- /dev/null
@@ -0,0 +1,42 @@
+# Evaluation semantics\r
+\r
+## Single equation\r
+\r
+Assume we have given the following definition:\r
+~~~\r
+f x = x + 1\r
+~~~\r
+\r
+Then the expression `f (f 13)` is evaluated in this way:\r
+\r
+~~~\r
+f (f 13)\r
+f (13 + 1)        because f 13 = 13 + 1\r
+f 14\r
+14 + 1            because f 14 = 14 + 1\r
+15\r
+~~~\r
+\r
+## Multiple equations\r
+\r
+If we have a more complicated function definition:\r
+~~~\r
+fib 1 = 1\r
+fib 2 = 1\r
+fib n = fib (n-1) + fib (n-2)\r
+~~~\r
+\r
+the expression `fib 4` is evaluated as\r
+\r
+ ~~~\r
+fib 4\r
+fib (4-1) + fib (4-2)              because fib 4 = fib (4-1) + fib (4-2)\r
+fib 3 + fib 2\r
+(fib (3-1) + fib (3-2)) + fib 2    because fib 3 = fib (3-1) + fib (3-2)\r
+fib 2 + fib 1 + fib 2              because fib 3 = fib (3-1) + fib (3-2)\r
+1 + fib 1 + fib 2                  because fib 2 = 1\r
+1 + 1 + fib 2                      because fib 1 = 1\r
+2 + fib 2     \r
+2 + 1                              because fib 2 = 1\r
+3\r
+ ~~~\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.04 Numbers.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.04 Numbers.md
new file mode 100644 (file)
index 0000000..85b75d1
--- /dev/null
@@ -0,0 +1,32 @@
+# Numbers\r
+\r
+## Numeric types\r
+\r
+The most important numeric type that are used by default are\r
+\r
+::data[Builtin/Integer, Builtin/Double]\r
+\r
+SCL standard library defines also other integer and floating point number types:\r
+\r
+::data[Builtin/Short, Builtin/Long, Builtin/Float, BigInteger/BigInteger]\r
+\r
+## Basic operations on numbers\r
+\r
+::value[Prelude/+,Prelude/-,Prelude/neg,Prelude/*,Prelude//]\r
+::value[Prelude/^,Prelude/sqrt,Prelude/exp,Prelude/log]\r
+::value[Prelude/pi,Prelude/sin,Prelude/cos,Prelude/tan,Prelude/asin,Prelude/acos,Prelude/atan,Prelude/atan2]\r
+::value[Prelude/min,Prelude/max,Prelude/abs,Prelude/floor,Prelude/ceil]\r
+::value[Prelude/div,Prelude/mod]\r
+\r
+## Comparison\r
+\r
+::value[Prelude/==,Prelude/!=]\r
+::value[Prelude/<,Prelude/<=,Prelude/>,Prelude/>=]\r
+\r
+## Conversion between numerical types\r
+\r
+::value[Prelude/fromInteger,Prelude/toInteger,Prelude/fromDouble,Prelude/toDouble]\r
+\r
+## Numerical operations on lists\r
+\r
+::value[Prelude/sum,Prelude/maximum,Prelude/minimum]
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.05 Lists.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.05 Lists.md
new file mode 100644 (file)
index 0000000..a7a4063
--- /dev/null
@@ -0,0 +1,131 @@
+# Lists\r
+\r
+## List literals\r
+\r
+A list with a constant length can be written by closing the list\r
+elements in brackets and separating the elements by commas:\r
+\r
+    [1,2,3]\r
+    []\r
+\r
+## List comprehension\r
+\r
+Lists can be formed with list comprehension expressions that\r
+resemble set comprehension in mathematics. For example\r
+\r
+    [x+1 | x <- lst]\r
+\r
+creates a list of all elements in `lst` increased by one\r
+and \r
+\r
+    [x+y | x <- lstX, y <- lstY]\r
+\r
+creates list of all sums of pairs where one element is in `lstX` and one in `lstY`.\r
+Note that the list may contain duplicates.\r
+\r
+It is possible to add also constraints \r
+\r
+    [x `div` 2 | x <- lst, x `mod` 2 == 0]\r
+\r
+and definitions\r
+\r
+    [x*y | x <- lst, y = x+1] \r
+\r
+Formally, a list comprehension expression is\r
+\r
+    [<expression> | <list qualifier>, ..., <list qualifier>]\r
+    \r
+where list qualifier can be one of the following\r
+\r
+* generator `<variable> <- <list expression>`\r
+* guard `<boolean>`\r
+* definition `<variable> = <expression>`\r
+* `then <expression> by <expression>`\r
+\r
+The last type of qualifier can be used to make operations that affects the\r
+whole list, for example\r
+\r
+    then drop 3\r
+    \r
+removes the first three elements and\r
+\r
+    then sortBy by x\r
+    \r
+sorts the elements by `x`.\r
+\r
+## Accessing the list elements\r
+\r
+The most basic way of reading list is to\r
+read it element by element.\r
+\r
+::value[Prelude/!]\r
+::value[Prelude/length]\r
+\r
+## Comparison\r
+\r
+Lists like almost all other types support the generic equality and comparison operations:\r
+\r
+::value[Prelude/==,Prelude/!=]\r
+::value[Prelude/<,Prelude/<=,Prelude/>,Prelude/>=]\r
+\r
+For example `lst == []` tests whether the `lst` is empty.\r
+The comparison of the list is lexicographic.\r
+\r
+## Executing code for each list element\r
+\r
+The only difference between the following iteration functions is\r
+the order of their parameters:\r
+\r
+::value[Prelude/iter, Prelude/for]\r
+\r
+## Concatenating lists\r
+\r
+::value[Prelude/+, Prelude/sum]\r
+\r
+## List transformations\r
+\r
+::value[Prelude/map]\r
+::value[Prelude/filter]\r
+::value[Prelude/join]\r
+::value[Prelude/concatMap]\r
+::value[Prelude/mapMaybe]\r
+\r
+::value[Prelude/zip]\r
+::value[Prelude/zipWith]\r
+::value[Prelude/unzip]\r
+\r
+## Ordering\r
+\r
+The following functions modify the order of the list elements:\r
+\r
+::value[Prelude/sort, Prelude/sortBy, Prelude/sortWith]\r
+::value[Prelude/reverse]\r
+\r
+## Sublists\r
+\r
+The following functions extract some sublist of the given list:\r
+\r
+::value[Prelude/take]\r
+::value[Prelude/drop]\r
+::value[Prelude/sub]\r
+\r
+## Aggregate operations\r
+\r
+Sometimes it is necessary to compute some kind of summary over\r
+all elements of a list. The most useful generic aggregate operation is `foldl`.\r
+\r
+::value[Prelude/foldl]\r
+\r
+It is used to define many more specialized aggreate operations such as\r
+\r
+    sum     = foldl (+) 0\r
+    product = foldl (*) 1\r
+    maximum = foldl1 max\r
+\r
+There is a variant that traverses the list from right to left: \r
+\r
+::value[Prelude/foldr]\r
+\r
+and a variant that that assumes that the list has at least one element:\r
+\r
+::value[Prelude/foldl1] 
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.06 Types.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.06 Types.md
new file mode 100644 (file)
index 0000000..2b1e69a
--- /dev/null
@@ -0,0 +1,178 @@
+# Types\r
+\r
+SCL is statically typed language which means that types of the possible values of all variables are known already\r
+at compile time. The following types (or more exactly, type constructors) have builtin support:\r
+\r
+* `Boolean`\r
+* `Byte`, `Short`, `Integer`, `Long`\r
+* `Float`, `Double`\r
+* `String`\r
+* `[]`\r
+* `()`, `(,)`, `(,,)`, ...\r
+* `Maybe`\r
+* `Vector`\r
+\r
+Other type constructors are either imported from the host language or defined in SCL modules.\r
+Except for the couple of special cases in the previous list, the names of all type constructors are capitalized.\r
+\r
+Some type constructors are parametric (compare to generics in Java or templates in C++).\r
+For example, the list type constructor `[]` has one parameter: the type of the list elements.\r
+Thus `[Integer]` is the type of the integer lists and `[String]` is the type of string lists.\r
+`[[Integer]]` is the type of the lists of integer lists. Parameters are usually\r
+written after the parametric type constructor: for example `Maybe String` or `Vector Integer`, but\r
+some of the builtin type constructors can be written in a special way in order to make the type\r
+expressions more readable:\r
+\r
+~~~\r
+[a] = [] a\r
+(a,b) = (,) a b\r
+(a,b,c) = (,,) a b c\r
+...\r
+~~~\r
+\r
+Particularly important type constructor is `->` for building function types. For example, the type\r
+of the function computing the length of a string is `String -> Integer`: the function takes a string\r
+as a parameter and returns an integer.\r
+\r
+Types of the functions taking multiple parameters are written by composing function types. For example,\r
+the type of a function taking nth element of a string list is `[String] -> Integer -> String`. The function\r
+takes a string list and an integer as a parameter and returns a string. Function type operator `->`\r
+is right associative thus the previous type is equivalent to `[String] -> (Integer -> String)`.\r
+Thus the type expression can be read as well as a type of functions taking a string list and returning another\r
+function from integers and strings.\r
+\r
+`(a,b)` is the type of pairs where the first component of the pair has type `a` and the second component has type `b`.\r
+Tuple types `(a,b,c)`, `(a,b,c,d)` etc. are defined similarly. `Maybe a` is the type of optional values.\r
+\r
+## Type annotations\r
+\r
+There are two kind of type annotations in SCL, both use `::` to separate\r
+the value from the type.\r
+\r
+Top-level annotations give a type for top-level definitions and they\r
+can be used only in SCL modules:\r
+\r
+    flip :: (a -> b -> <e> c) -> b -> a -> <e> c\r
+    flip f x y =  f y x\r
+\r
+Inline annotations may be embedded in expressions or patterns:\r
+\r
+    execute (print (getVar "PI1#PI12_PRESSURE" :: Double))\r
+\r
+SCL compiler can usually infer the type of the expressions but there\r
+are couple of reasons to use annotations. They\r
+\r
+* document the definitions\r
+* prevents some typos that would change the type\r
+* restrict the type to be more specific than what the compiler can infer\r
+* prevents the compiler from making a bad guess for the type\r
+\r
+## Type variables\r
+\r
+Many functions can be defined so that they do not need to know the exact types they are operating with.\r
+Such unknown types can be filled in type expressions by type variables: for example the function we\r
+discussed earlier that took nth element of a string list does not need the information that list elements\r
+are strings in its implementation and so it can be given a more generic type `[a] -> Integer -> a`,\r
+i.e a function taking a list of `a`:s and an integer as a parameter and returning a single `a`.\r
+\r
+Function types with type variables tell quite much about the function assuming it is total,\r
+i.e does not hang or throw a runtime exception with any parameters. For example the type\r
+signatures define the following functions uniquely:\r
+\r
+~~~\r
+id :: a -> a\r
+swap :: (a,b) -> (b,a)\r
+const :: a -> b -> a\r
+~~~\r
+\r
+and there are only two possible total functions satisfying the following signature\r
+\r
+~~~\r
+choose :: a -> a -> a\r
+~~~\r
+\r
+Type variables may also refer to parametric types, but all useful examples involve type constraints we describe below.\r
+\r
+## Type constraints\r
+\r
+SCL does not support function overloading at least in the way Java and C++ support it.\r
+This means that every function has a unique type signature. Now consider the addition function `(+)`.\r
+We could defined its signature for example as `Integer -> Integer -> Integer`,\r
+but then we would need some other name for the sum of doubles `Double -> Double -> Double`\r
+or strings `String -> String -> String`. It would seem like the right signature would be\r
+`a -> a -> a`, but that is not satisfactory either, because then the function had to\r
+somehow support all possible types. \r
+\r
+The solution to the problem is to constraint the set of allowed types for the type variable.\r
+Such a constrained type is written in the case of addition function as \r
+`Additive a => a -> a -> a`. The constraint `Additive a` is composed of a type class\r
+`Additive` followed by parameters of the constraint. The type can be understood in\r
+two different ways. A logical reading is\r
+> for any additive type `a`, the function takes two `a`:s as parameters and returns `a`\r
+and operational reading that gives a good intuition what is happening in runtime\r
+> the function takes a parameter `Additive a` that describes a set of methods that\r
+> can be used to operate values of `a` and two `a`:s and returns `a`\r
+\r
+Constrained type variable can be also parametric. For example, let's say we want\r
+to define a function `getNth` that takes nth element of a list but also works with arrays.\r
+The signature would then be\r
+\r
+~~~\r
+getNth :: Sequence s => s a -> Integer -> a\r
+~~~\r
+\r
+Type classes form a hierarchy: each class may have any number of superclasses.\r
+Only the most specific type class is needed in the constraints. For example,\r
+addition and multiplication have the following signatures:\r
+\r
+~~~\r
+(+) :: Additive a => a -> a -> a\r
+(*) :: Ring a => a -> a -> a\r
+~~~\r
+\r
+and `Additive a` is a superclass of `Ring a`. A function using both operators need to specify only `Ring a` as a constraint:\r
+\r
+~~~\r
+doubleAndAddOne :: Ring a => a -> a\r
+doubleAndAddOne x = 2*x + 1\r
+~~~\r
+\r
+## Effect types\r
+\r
+SCL functions are [referentially transparent]("http://en.wikipedia.org/wiki/Referential_transparency_(computer_science)")\r
+which means that they are like mathematical functions always returning the same value for the same\r
+parameters and not causing any observable side-effects. This seems extremely restrictive\r
+because most of the programs are written in order to generate some kind of side-effects and even\r
+completely mathematical algorithms involve functions that are not referentially transparent such as\r
+generation of random numbers.\r
+\r
+SCL manages side-effects with *effect types*.\r
+An effectful computation has type `<effects> t`.\r
+The type after angle brackets is the type of the value returned by the computation.\r
+Side-effects that might happen during computation are listed inside of the angle brackets.\r
+Effect types must always occur as a return type of a function. Here are some examples of functions with side-effects:\r
+\r
+~~~\r
+randomBetween :: Double -> Double -> <Nondet> Double\r
+resourceByUri :: String -> <ReadGraph> Resource\r
+claim :: Resource -> Resource -> Resource -> <WriteGraph> ()\r
+randomLiteral :: Double -> Double -> <Nondet,WriteGraph> Resource\r
+~~~\r
+\r
+Effect types are much like type constraints: you can mostly ignore them when using functions.\r
+All effects you use are automatically collected and added to the type signature of the defined\r
+function (or checked against type annotation if provided).\r
+\r
+Like type classes, effects form a hierarchy. For example `WriteGraph` inherits `ReadGraph`\r
+and a function both reading and writing to graph is annotated only with `<WriteGraph>` effect.\r
+\r
+Like types, effects can also be abstracted with effect variables. This is important when\r
+defining generic functions that manipulate possibly effectful functions:\r
+\r
+~~~\r
+executeTwice :: (() -> <e> ()) -> <e> ()\r
+executeTwice f = { f () ; f () }\r
+\r
+(.) :: (b -> <e2> c) -> (a -> <e1> b) -> (a -> <e1,e2> c)\r
+(f . g) x = f (g x)\r
+~~~
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.07 Booleans.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.07 Booleans.md
new file mode 100644 (file)
index 0000000..2ef00da
--- /dev/null
@@ -0,0 +1,5 @@
+# Booleans\r
+\r
+::value[Prelude/&&, Prelude/||, Prelude/not, Prelude/and, Prelude/or, Prelude/all, Prelude/any]\r
+\r
+\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.08 Side effects.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.08 Side effects.md
new file mode 100644 (file)
index 0000000..801569b
--- /dev/null
@@ -0,0 +1,34 @@
+# Side effects\r
+\r
+Even if the functional programming style prefers writing\r
+pure functions without side-effects, sometimes side-effects\r
+are the reason for running the function in the first place.\r
+\r
+This section lists the most important functions with\r
+side-effects that are defined in the SCL standard library.\r
+\r
+## Printing\r
+\r
+::value[Prelude/print, Prelude/printString, Prelude/printError, Prelude/printingToFile]\r
+\r
+## References\r
+\r
+::value[Prelude/ref, Prelude/getRef, Prelude/:=]\r
+\r
+## Mutable arrays\r
+\r
+::data[ArrayList/T]\r
+::value[ArrayList/new]\r
+::value[ArrayList/add]\r
+::value[ArrayList/remove]\r
+::value[ArrayList/get]\r
+::value[ArrayList/length]\r
+::value[ArrayList/contains]\r
+\r
+::value[ArrayList/iter, ArrayList/for]\r
+::value[ArrayList/mapInPlace]\r
+::value[ArrayList/popUntilEmpty]\r
+\r
+## Escaping side-effects\r
+\r
+::value[Builtin/runProc]
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.09 Strings.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.09 Strings.md
new file mode 100644 (file)
index 0000000..224786d
--- /dev/null
@@ -0,0 +1,13 @@
+# Strings\r
+\r
+Strings are essentially lists of (Unicode) characters and therefore many functions that operate\r
+on lists can also be used with strings:\r
+\r
+::value[Prelude/+, Prelude/sum, Prelude/length, Prelude/take, Prelude/drop, Prelude/sub]\r
+\r
+Strings have currently their own function for accessing indivial characters\r
+(but in the future they may also support `!` operator). \r
+\r
+::value[Prelude/charAt]\r
+\r
+The following operations are often useful for \r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.10 Optional values (Maybe).md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.10 Optional values (Maybe).md
new file mode 100644 (file)
index 0000000..a71014f
--- /dev/null
@@ -0,0 +1,8 @@
+# Optional values (Maybe)\r
+\r
+The type `Maybe a` can be used in situations where some value can \r
+not be necessarily computed. Its values are either `Nothing` or\r
+`Just v` where the type of `v` is `a`.\r
+\r
+::data[Builtin/Maybe]\r
+::value[Prelude/fromJust, Prelude/fromMaybe, Prelude/execJust, Prelude/filterJust, Prelude/orElse, Prelude/elemMaybe]\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.11 Functions.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.11 Functions.md
new file mode 100644 (file)
index 0000000..4e5264e
--- /dev/null
@@ -0,0 +1,6 @@
+## Functions\r
+\r
+Because functions are values, there are also functions that operate on them\r
+\r
+::value[Prelude/$, Prelude/.]\r
+\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.12 Tuples.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.12 Tuples.md
new file mode 100644 (file)
index 0000000..d63d7e6
--- /dev/null
@@ -0,0 +1,8 @@
+# Tuples\r
+\r
+A tuple is fixed length sequence of values that may have different types.\r
+Tuples are constructed by listing their components in parentheses\r
+\r
+    (1, "a", 5.4)\r
+\r
+::value[Prelude/fst, Prelude/snd, Prelude/curry, Prelude/uncurry]\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.02 Model configuration.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.02 Model configuration.md
new file mode 100644 (file)
index 0000000..c881ca5
--- /dev/null
@@ -0,0 +1,43 @@
+\r
+# Model configuration\r
+\r
+Apros 6.05 contains a new module `Apros/Legacy` for manipulating the model configuration\r
+with commands that are familiar to Apros 5 developers. Idea of the module is that\r
+all Apros entities are referred by their names in the Apros solver.\r
+\r
+## Updating model configuration\r
+\r
+::value[Apros/Legacy/aadd, Apros/Legacy/aaddNonvisual, Apros/Legacy/amodi, Apros/Legacy/aconnect, Apros/Legacy/aconnectWithName]\r
+::value[Apros/Legacy/ainclude, Apros/Legacy/aexclude, Apros/Legacy/arename]\r
+\r
+## Examples\r
+\r
+The following commands build a point-pipe-point configuration to subprocess MYDIAGRAM.\r
+\r
+    import "Apros/Legacy" \r
+    aadd "MYDIAGRAM" "Point" "PO01" (50, 50)\r
+    amodi "PO01" "PO11_PRESSURE" 0.2\r
+    aexclude "PO01"\r
+   \r
+    aadd "MYDIAGRAM" "Point" "PO02" (100, 50)\r
+    amodi "PO02" "PO11_PRESSURE" 0.1\r
+    aexclude "PO02"\r
+   \r
+    aadd "MYDIAGRAM" "Pipe" "PIP01" (75, 50)\r
+    amodi "PIP01" "PI12_CONNECT_POINT_1" "PO01"\r
+    amodi "PIP01" "PI12_CONNECT_POINT_2" "PO02"\r
+\r
+Alternatively `aconnect` can be used to create the same name reference connections:\r
+\r
+    aconnect "PO01" "SelfPOINT" "PIP01" "PI12_CONNECT_POINT_1" \r
+    aconnect "PO02" "SelfPOINT" "PIP01" "PI12_CONNECT_POINT_2" \r
+\r
+Notice the attribute name "SelfPOINT" which represents the MODNAME terminal of the POINT module.\r
+To make a reference to a module's MODNAME terminal, use "SelfMT" as the attribute name, where\r
+MT is the module type name in uppercase.\r
+\r
+## Making model queries\r
+\r
+The module contains also the basic commands for making model queries:\r
+\r
+::value[Apros/Legacy/ashow, Apros/Legacy/alist, Apros/Legacy/alistOnly, Apros/Legacy/aget, Apros/Legacy/amget, Apros/Legacy/amgetSort]\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.03 (Exercise) Pipelines.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.03 (Exercise) Pipelines.md
new file mode 100644 (file)
index 0000000..6e19955
--- /dev/null
@@ -0,0 +1,199 @@
+[pipes.txt]: "http://www.simantics.org/~niemisto/SCL20150513/pipes.txt"\r
+\r
+## Pipelines exercise\r
+\r
+In this exercise, you create a model configuration based on the data in the file [pipes.txt].\r
+\r
+### Step 1\r
+\r
+Implement a function\r
+\r
+    isNonemptyString :: String -> Boolean\r
+\r
+that returns true, when the string given as a parameter is nonempty:\r
+\r
+    > isNonemptyString ""\r
+    False\r
+    > isNonemptyString "foo"\r
+    True\r
+\r
+You need the empty string `""` and the inequality comparison:\r
+    \r
+::value[Prelude/!=]\r
+\r
+### Step 2\r
+\r
+Implement a function\r
+\r
+    removeComment :: String -> String\r
+\r
+that removes a comment from a line. A comment starts with `!` and continues\r
+to the end of the line. It should also remove leading and trailing whitespace. For example\r
+    \r
+    > removeComment "A;B;C ! This is a comment"\r
+    "A;B;C"\r
+    > removeComment "Hello World!"\r
+    "Hello World"\r
+    > removeComment "This line contains no comments."\r
+    "This line contains no comments."\r
+\r
+The following functions are useful here:\r
+\r
+::value[Prelude/splitString, Prelude/!, Prelude/trim]\r
+\r
+### Step 3\r
+\r
+New, lets read the file [pipes.txt]. Store it to somewhere in your file system.\r
+\r
+You need to import the module `StringIO`, either using the import dialog or\r
+with the command\r
+\r
+    import "StringIO"\r
+\r
+Now, try to read the file using\r
+\r
+::value[StringIO/readLines]\r
+\r
+Remember that `\` is an escape character in SCL. A string containing directory separators\r
+must be written in one of the following forms:\r
+\r
+    "c:/temp/pipes.txt"\r
+    "c:\\temp\\pipes.txt"\r
+\r
+### Step 4\r
+\r
+As you see, the file contains empty lines and comments. Implement a function\r
+\r
+    loadAndPreprocess :: String -> <Proc> [String]\r
+    \r
+that reads the file, whose name is given as a parameter, removes the comments, empty lines and leading and trailing\r
+whitespace at every line. It returns the preprocessed lines. You need the\r
+functions `isNonemptyString`, `removeComment` you implemented before,\r
+`readLines` and the following functions\r
+\r
+::value[Prelude/map,Prelude/filter]\r
+\r
+### Step 5\r
+\r
+Create a new SCL module and move your definitions there (if you have not done so already). It\r
+is much easier to continue handling the increasing number of function definitions there.\r
+\r
+### Step 6\r
+\r
+You may have noticed that the lines in the preprocessed file have entries separated by `;`.\r
+The first entry in each line is either "POINT" or "PIPE". Implement the functions \r
+\r
+    isPointLine, isPipeLine :: [String] -> Boolean\r
+\r
+that check whether the first string in a list of strings is "POINT" or "PIPE".\r
+For example\r
+\r
+    > isPointLine ["POINT", "1", "2", "3.4", "100", "200"]\r
+\r
+### Step 7\r
+\r
+Now, add the following definitions to your SCL module:\r
+\r
+~~~\r
+handlePointEntry :: String -> [String] -> <Proc> ()\r
+handlePointEntry diagram ["POINT", id, pointElevation, x, y] = do\r
+    print "Add a point \(id) into the diagram \(diagram) with elevation \(pointElevation) at coordinates \(x),\(y)."\r
+    \r
+handlePipeEntry :: String -> Integer -> [String] -> <Proc> ()\r
+handlePipeEntry diagram id ["PIPE", id1, id2, pipeLength] = do\r
+    print "Add a pipe \(id) into the diagram \(diagram) connecting the point \(id1) to the point \(id2) with length \(pipeLength)"\r
+~~~\r
+\r
+Create a function\r
+\r
+    readPipesFile :: String -> String -> <Proc> ()\r
+    \r
+that is called as\r
+\r
+    readPipesFile "diagramName" "fileName"\r
+    \r
+It should first read the file and preprocess it using `loadAndPreprocess` you implemented in Step 4.\r
+It should then split each line into entries with `splitString` and `map`\r
+Note that because of the order of the parameters of `splitString` you need either anonymous\r
+functions, a separate funtion definition or\r
+::value[Prelude/flip]\r
+\r
+It should then filter the lines into two lists, one containing all definitions of points\r
+and one all definitions of pipes. Finally, the function should call \r
+`handlePointEntry` for all points using\r
+\r
+::value[Prelude/iter]\r
+\r
+and `handlePipeEntry` for all pipes using (because `handlePipeEntry` has an extra integer parameter)\r
+\r
+::value[Prelude/iterI] \r
+\r
+When finished the function should work like this from the console:\r
+\r
+~~~\r
+> readPipesFile "X" "c:/temp/pipes.txt"\r
+Add a point 1 into the diagram X with elevation 0 at coordinates 100,100.\r
+Add a point 2 into the diagram X with elevation 1.1 at coordinates 120,100.\r
+Add a point 3 into the diagram X with elevation 1.5 at coordinates 140,100.\r
+Add a point 4 into the diagram X with elevation 2.5 at coordinates 160,100.\r
+Add a pipe 0 into the diagram X connecting the point 1 to the point 2 with length 12\r
+Add a pipe 1 into the diagram X connecting the point 2 to the point 3 with length 11\r
+Add a pipe 2 into the diagram X connecting the point 3 to the point 4 with length 13\r
+~~~\r
+\r
+### Step 8\r
+\r
+Reimplement the function `handlePointEntry` so that it creates the points into the diagram with the\r
+specified elevation and diagram coordinates. You need the functions\r
+\r
+::value[Apros/Legacy/aadd, Apros/Legacy/amodi]\r
+\r
+You need also the function\r
+\r
+::value[Prelude/read]\r
+\r
+to convert the diagram coordinates from strings to doubles.\r
+Add some prefix to the point indicies to form the point name (for example\r
+`name = "PO" + id`. The name of the elevation attribute is\r
+`PO11_ELEV`.\r
+\r
+Test your implementation with the example data.\r
+\r
+### Step 9\r
+\r
+Reimplement the function `handlePipeEntry` so that it creates the pipes into the diagram with\r
+the specified length (`PI12_LENGTH`) and connects it to the specified points\r
+(`PI12_CONNECT_POINT_1` and `PI12_CONNECT_POINT_2`). You may place the pipes to the origin\r
+`(0,0)`.\r
+\r
+Test your implementation again with the example data.\r
+\r
+### Step 10\r
+\r
+In this final step, fix the coordinates of the pipes so that they are located between the points\r
+they connect.\r
+\r
+You may do this in the following way. In `readPipesFile`, define a function\r
+    \r
+    coordinates :: String -> Maybe (Double, Double)\r
+    \r
+that gives the coordinates of a point when given the index of the point. You may create it\r
+by partially applying the function\r
+\r
+::value[Prelude/index]\r
+\r
+for this. Then, add the new parameter `coordinates` to the function `handlePipeEntry` so that\r
+its signature becomes\r
+\r
+    String -> (String -> Maybe (Double, Double)) -> Integer -> [String] -> <Proc> ()\r
+    \r
+Now, you may read the coordinates of the points in `handlePipeEntry` like this\r
+\r
+    (x1,y1) = fromJust (coordinates id1)\r
+    \r
+where\r
+\r
+::value[Prelude/fromJust]\r
+\r
+Use the average of the connected points as the diagram coordinate for the pipe.\r
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.04 (Exercise) Polyline.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.04 (Exercise) Polyline.md
new file mode 100644 (file)
index 0000000..f78059c
--- /dev/null
@@ -0,0 +1,67 @@
+## Polyline exercise\r
+\r
+### Step 1\r
+\r
+Implement a function\r
+\r
+    addPolyline :: String -> String -> (Double,Double) -> [(Double,Double)] -> <Proc> ()\r
+\r
+that is called as\r
+\r
+    addPolyline diagramName name location polylineData\r
+\r
+It creates a polyline `name` to the diagram `diagramName` at `location`.\r
+The polyline should interpolate the points `polylineData`\r
+(assumed in this step to contain at most 30 points).\r
+\r
+You need the following functions:\r
+\r
+::value[Apros/Legacy/aadd,Apros/Legacy/amodi]\r
+\r
+And the following symbol and attributes\r
+\r
+    Polyline\r
+        FUNCTION_X_COORDINATE(i)\r
+        FUNCTION_Y_COORDINATE(i)\r
+        FUNCTION_OK(i)\r
+\r
+Test that your function produces a functional model configuration.\r
+\r
+### Step 2\r
+\r
+Extend your function so that it supports also `polylineList` with more\r
+than 30 points. For example\r
+\r
+    addPolyline "Diagram" "PL" (100,100) [(x,sin x) | i <- [0..100], x = 0.1*fromInteger i]\r
+\r
+might produce the following model configuration:\r
+\r
+![](http://www.simantics.org/~niemisto/SCL20150513/Polyline.png)\r
+\r
+You may implement the polyline using the following symbols and attributes\r
+\r
+    Polyline\r
+        FUNCTION_X_COORDINATE(i)\r
+        FUNCTION_Y_COORDINATE(i)\r
+        FUNCTION_OK(i)\r
+        FUNCTION_INPUT_SIGN\r
+        FUNCTION_OUTPUT_SIGN\r
+    BranchAnalog\r
+        AMUX_INPUT_SIGN\r
+        AMUX_OUTPUT_SIGN(i)\r
+    LV_CHECKER\r
+        LVC_INPUT_SIGN\r
+        LVC_LIMIT_VALUE\r
+        LVC_OUTPUT_SIGN_1\r
+    ANALOG_SWITCH\r
+        SWITCH_CONTROL_S\r
+        SWITCH_INP_SIGN_1\r
+        SWITCH_INP_SIGN_2\r
+        SWITCH_OUTP_SIGN\r
+\r
+\r
+You need in addition to `aadd` and `amodi` the function\r
+\r
+::value[Apros/Legacy/aconnect]\r
+\r
+Test that your function produces a functional model configuration.
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.05 Semantic graph.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.05 Semantic graph.md
new file mode 100644 (file)
index 0000000..edd800d
--- /dev/null
@@ -0,0 +1,59 @@
+# Operating on the semantic graph\r
+\r
+All model configurations in Simantics are stored into a semantic graph database.\r
+Therefore it is the most primitive interface for accessing Simantics and in\r
+principle everything is doable with it, although sometimes with a great effort.\r
+\r
+## Understanding semantic graphs\r
+\r
+The best tool for discovering how the model configuration is represented\r
+in the Simantics, is Graph debugger. It can be opened from\r
+**Window/Show View/Other**. Resources can be dragged to the debugger\r
+from the model browser.\r
+\r
+The debugger shows the URI of the resource and all statements related\r
+to it.\r
+\r
+## Accessing resources\r
+\r
+::data[Simantics/DB/Resource]\r
+::value[Simantics/DB/resource,Simantics/DB/relativeResource,Simantics/DB/possibleResource,Simantics/DB/uriOf]\r
+::value[Simantics/DB/currentModel]\r
+\r
+## Navigating\r
+\r
+::value[Simantics/DB/#,Simantics/DB/possibleObject,Simantics/DB/singleObject]\r
+::data[Simantics/DB/Statement]\r
+::value[Simantics/DB/statements,Simantics/DB/singleStatement]\r
+\r
+## Reading literal values\r
+\r
+::value[Simantics/DB/relatedValue, Simantics/DB/nameOf]\r
+\r
+## Type queries\r
+\r
+::value[Simantics/DB/isInstanceOf, Simantics/DB/isSubrelationOf, Simantics/DB/isInheritedFrom]\r
+::value[Simantics/DB/singleTypeOf, Simantics/DB/possibleTypeOf] \r
+\r
+## Transactions\r
+\r
+The graph database can be accessed only in reading or writing transactions. The SCL console\r
+creates the transaction automatically if necessary, but sometimes it is necessary to control\r
+manually where the transactions are started.\r
+\r
+::value[Simantics/DB/syncRead, Simantics/DB/syncWrite, Simantics/DB/asyncRead, Simantics/DB/asyncWrite] \r
+\r
+## Writing\r
+\r
+::value[Simantics/DB/newResource, Simantics/DB/claim, Simantics/DB/claimRelatedValue]\r
+::value[Simantics/DB/deny]\r
+\r
+## Entities\r
+\r
+::class[Simantics/Entity/Entity]\r
+\r
+## Searching\r
+\r
+::value[Simantics/Model/searchByType, Simantics/Model/searchByTypeShallow, Simantics/Model/searchByTypeAndName]\r
+::value[Simantics/Model/searchByTypeAndNameShallow, Simantics/Model/searchByQuery, Simantics/Model/searchByQueryShallow]\r
+    Simantics/Model/searchByTypeAndFilter
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.06 (Exercise) Pipelines again.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.06 (Exercise) Pipelines again.md
new file mode 100644 (file)
index 0000000..5bd4383
--- /dev/null
@@ -0,0 +1,79 @@
+## Pipelines again\r
+\r
+In this exercise, we write points and pipes of a\r
+diagram in the same format used earlier for reading.\r
+\r
+### Step 1\r
+\r
+Use\r
+\r
+::value[Simantics/DB/relativeResource]\r
+\r
+and \r
+\r
+::value[Simantics/DB/currentModel]\r
+\r
+to define a variable `dia` that refers to some composite (configuration element\r
+corresponding to a diagram). Create some content (points and pipes) to\r
+the diagram.\r
+\r
+Print the value to the console and check that it corresponds to the\r
+resource id given by the graph debugger.\r
+\r
+### Step 2\r
+\r
+Import the ontology `http://www.simantics.org/Layer0-1.1` as `L0`.\r
+\r
+Use \r
+\r
+::value[Simantics/DB/#]\r
+\r
+and `L0.ConsistsOf` to find all children of `dia`.\r
+Print their names using\r
+\r
+::value[Prelude/map, Simantics/DB/nameOf]\r
+\r
+### Step 3\r
+\r
+Import the ontology `http://www.apros.fi/Combustion/Configuration-6.0` as `Conf`.\r
+\r
+Modify the commands in step 2 to find only the points (`Conf.ModuleTypes.POINT`) of the diagram. \r
+\r
+### Step 4 \r
+\r
+Print the names and elevations of all points in `dia` using the function\r
+\r
+::value[Simantics/DB/relatedValue]\r
+\r
+and the attribute `Conf.Relations.PO11_ELEV`.\r
+\r
+### Step 5 \r
+\r
+Use the relation `http://www.simantics.org/Modeling-1.2/ElementToComponent`\r
+and \r
+\r
+::value[Simantics/DB/singleObject]\r
+\r
+to find the graphical symbol of the point.\r
+\r
+Use the relation `http://www.simantics.org/Diagram-2.2/HasTransform` and\r
+\r
+::value[Simantics/DB/relatedValue]\r
+\r
+to read the transformation of the point. The last two elements of the transformation\r
+are the coordinates of the point.\r
+\r
+### Step 6\r
+\r
+Give an indices for all points you find for example using\r
+\r
+::value[Prelude/range, Prelude/zip]\r
+\r
+### Step 7\r
+\r
+Print the data about the points in the format described in\r
+the previous pipelines exercise.\r
+\r
+### Step 8\r
+\r
+Print the corresponding data about the pipes.
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.07 (Solution) Pipelines.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.07 (Solution) Pipelines.md
new file mode 100644 (file)
index 0000000..36bbe27
--- /dev/null
@@ -0,0 +1,48 @@
+## Pipelines solution\r
+\r
+~~~\r
+import "StringIO"\r
+import "Apros/Legacy"\r
+\r
+isNonemptyString :: String -> Boolean\r
+isNonemptyString = (!= "")\r
+\r
+removeComment :: String -> String\r
+removeComment text = (splitString text "!")!0\r
+\r
+loadAndPreprocess :: String -> <Proc> [String]\r
+loadAndPreprocess = filter isNonemptyString . map (trim . removeComment) . readLines\r
+\r
+isPointEntry entry = (entry!0) == "POINT"\r
+isPipeEntry entry = (entry!0) == "PIPE"\r
+\r
+handlePointEntry diagram ["POINT", id, pointElevation, x, y] = do\r
+    name = "PO" + id\r
+    aadd diagram "POINT" name (read x, read y)\r
+    amodi name "PO11_ELEV" pointElevation\r
+    \r
+handlePipeEntry :: String -> (String -> Maybe (Double, Double)) -> Integer -> [String] -> <Proc> ()\r
+handlePipeEntry diagram coordinates id ["PIPE", id1, id2, pipeLength] = do\r
+    name = "PI" + show id\r
+    name1 = "PO" + id1\r
+    name2 = "PO" + id2\r
+    (x1,y1) = fromJust (coordinates id1)\r
+    (x2,y2) = fromJust (coordinates id2)\r
+    aadd diagram "PIPE" name (0.5*(x1+x2), 0.5*(y1+y2))\r
+    amodi name "PI12_CONNECT_POINT_1" name1\r
+    amodi name "PI12_CONNECT_POINT_2" name2\r
+    amodi name "PI12_LENGTH" pipeLength\r
+\r
+processFile :: String -> String -> <Proc> ()\r
+processFile diagram fileName = do\r
+    entries = map (flip splitString ";") $ loadAndPreprocess fileName\r
+    \r
+    // Points\r
+    pointEntries = filter isPointEntry entries\r
+    iter (handlePointEntry diagram) pointEntries\r
+    coordinates = index [(id, (read x, read y)) | [_,id,_,x,y] <- pointEntries]\r
+    \r
+    // Pipes \r
+    pipeEntries = filter isPipeEntry entries\r
+    iterI (handlePipeEntry diagram coordinates) pipeEntries\r
+~~~
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.08 (Solution) Polyline.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.08 (Solution) Polyline.md
new file mode 100644 (file)
index 0000000..6926c48
--- /dev/null
@@ -0,0 +1,40 @@
+## Polyline solution\r
+\r
+~~~\r
+import "Apros/Legacy"\r
+\r
+connect (ma,ca) (mb,cb) = aconnect ma ca mb cb\r
+\r
+addPolyline :: String -> String -> (Double,Double) -> [(Double,Double)] -> <Proc> ()\r
+addPolyline diagram name position xyPoints = ignore $ addRecursively 1 position xyPoints\r
+  where\r
+    addRecursively n position xyPoints | length xyPoints <= 30 = \r
+        addSmallPolyline n position xyPoints\r
+    addRecursively n (x,y) xyPoints = do\r
+        swPoint = fst (xyPoints!29)\r
+        brName = name + "_BR" + show n\r
+        lvName = name + "_LV" + show n\r
+        swName = name + "_SW" + show n\r
+        aadd diagram "BranchAnalog" brName (x-20, y+5) \r
+        aadd diagram "LV_CHECKER" lvName (x, y)\r
+        amodi lvName "LVC_LIMIT_VALUE" (fst (xyPoints!29))\r
+        aadd diagram "ANALOG_SWITCH" swName (x+20, y+5)\r
+        (in1, out1) = addSmallPolyline n     (x, y+10) (take 30 xyPoints)\r
+        (in2, out2) = addRecursively   (n+1) (x, y+20) (drop 29 xyPoints)\r
+        connect (brName, "AMUX_OUTPUT_SIGN(1)") (lvName, "LVC_INPUT_SIGN")\r
+        connect (brName, "AMUX_OUTPUT_SIGN(2)") in1       \r
+        connect (brName, "AMUX_OUTPUT_SIGN(4)") in2\r
+        connect (lvName, "LVC_OUTPUT_SIGN_1")   (swName, "SWITCH_CONTROL_S")\r
+        connect out1                            (swName, "SWITCH_INP_SIGN_1")\r
+        connect out2                            (swName, "SWITCH_INP_SIGN_2")\r
+        ((brName, "AMUX_INPUT_SIGN"), (swName, "SWITCH_OUTP_SIGN"))    \r
+    addSmallPolyline n position xyPoints = do\r
+        fullName = name + "_" + show n\r
+        aadd diagram "Polyline" fullName position\r
+        for [1..length xyPoints] $ \i -> do\r
+            (x,y) = xyPoints!(i-1)\r
+            amodi fullName "FUNCTION_X_COORDINATE(\(i))" x\r
+            amodi fullName "FUNCTION_Y_COORDINATE(\(i))" y\r
+            amodi fullName "FUNCTION_OK(\(i))"           True\r
+        ((fullName, "FUNCTION_INPUT_SIGN"), (fullName, "FUNCTION_OUTPUT_SIGN")) \r
+~~~
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.09 (Solution) Pipelines again.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/2.09 (Solution) Pipelines again.md
new file mode 100644 (file)
index 0000000..d614d53
--- /dev/null
@@ -0,0 +1,35 @@
+## Pipelines again solution\r
+\r
+~~~\r
+import "Simantics/DB"\r
+import "http://www.simantics.org/Layer0-1.1" as L0\r
+import "http://www.simantics.org/Modeling-1.2" as MOD\r
+import "http://www.simantics.org/Diagram-2.2" as DIA\r
+import "http://www.apros.fi/Combustion/Configuration-6.0" as Conf\r
+\r
+swap (x,y) = (y,x)\r
+\r
+connectPoint1 :: Resource -> <ReadGraph> Resource\r
+connectPoint1 r = do\r
+    c = singleObject r Conf.Relations.PI12_CONNECT_POINT_1_1_1\r
+    singleObject c Conf.Relations.SelfPOINT.Inverse\r
+\r
+connectPoint2 :: Resource -> <ReadGraph> Resource\r
+connectPoint2 r = do\r
+    c = singleObject r Conf.Relations.PI12_CONNECT_POINT_2_1_1\r
+    singleObject c Conf.Relations.SelfPOINT.Inverse\r
+\r
+readDiagram :: Resource -> <ReadGraph,Proc> ()\r
+readDiagram dia = do\r
+    points = filter (flip isInstanceOf Conf.ModuleTypes.POINT) (dia # L0.ConsistsOf)\r
+    indexedPoints = zip [0..length points] points\r
+    for indexedPoints $ \(i,r) -> do\r
+        trans = relatedValue (singleObject r MOD.ComponentToElement) DIA.HasTransform :: [Double]\r
+        print "POINT;\(i);\(relatedValue r Conf.Relations.PO11_ELEV :: Float);\(trans!4);\(trans!5)"\r
+    pointByResource = index (map swap indexedPoints)\r
+    pipes = filter (flip isInstanceOf Conf.ModuleTypes.PIPE) (dia # L0.ConsistsOf)\r
+    for pipes $ \r -> do\r
+        id1 = fromJust (pointByResource (connectPoint1 r))\r
+        id2 = fromJust (pointByResource (connectPoint2 r))\r
+        print "PIPE;\(id1);\(id2);\(relatedValue r Conf.Relations.PI12_LENGTH :: Float)"\r
+~~~
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.01 Simulation sequences.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.01 Simulation sequences.md
new file mode 100644 (file)
index 0000000..81108c0
--- /dev/null
@@ -0,0 +1,116 @@
+# Simulation sequences\r
+\r
+## Sequence monad\r
+    \r
+::data[Simantics/Sequences/Sequence]\r
+    \r
+We call the sequence *instantious*, if its duration is zero, i.e, the sequence finishes immediately after started.\r
+\r
+A cooking recipe is an example of a sequence in the real world. Its return value could be for example the success \r
+indication of the cooking process.\r
+\r
+    instance Monad Sequence\r
+\r
+In order to build complex sequences from simple primitives, the sequences implement\r
+[Monad](http://en.wikipedia.org/wiki/Monad_%28functional_programming%29) operations and\r
+its laws. These are\r
+\r
+::value[Prelude/return, Prelude/>>=]\r
+    \r
+The sequence `return v` has zero duration, it does not modify the simulator state and returns `v`. The sequence `seqA >>= f` is a sequence that first behaves like `seqA`, and when it has completed and returned a value `resultA`, continues like the sequence `f resultA`. In other words, `(>>=)` concatenates two sequences and the behavior of the latter sequence may depend on the return value of the former sequence. \r
+\r
+::value[Prelude/>>, Prelude/fmap, Prelude/join, Prelude/sequence, Prelude/repeatForever]\r
+    \r
+These operations are derived from the primitive monad operations.\r
+The sequence `seqA >> seqB` behaves first like `seqA` and when it has finished it\r
+continues like `seqB`. The sequence `fmap f seq` maps the result of the sequence `seq` by the function\r
+`f`. The sequence `join seq` first behaves like the sequence `seq` and then like the sequence `seq` returned.\r
+The sequence `sequence seqs` executes every sequence in the container `seqs` sequentially. The container can be for example list or `Maybe`. The sequence `repeatForever seq` repeats the sequence `seq` forever, never returning.\r
+\r
+## Actions\r
+\r
+    effect Action\r
+    \r
+`<Action> a` is an instantious operation happening in the simulator and returning a value of type `a`. It can be a pure reading operation, but may also modify the simulator state. The duration of an action is always zero.\r
+\r
+::value[Simantics/Sequences/time, Simantics/Sequences/getVar, Simantics/Sequences/setVar]\r
+    \r
+::value[Simantics/Sequences/execute]\r
+\r
+Multiple actions happening at the same time may be written either as separate sequences:\r
+\r
+    mdo execute (setVar "SP1#SP_VALUE" 13)\r
+        execute (setVar "SP2#SP_VALUE" 14)\r
+\r
+or as one sequence with more complicated action:\r
+\r
+    execute do\r
+        setVar "SP1#SP_VALUE" 13\r
+        setVar "SP2#SP_VALUE" 14\r
+\r
+## Controlling time\r
+\r
+::value[Simantics/Sequences/waitStep]\r
+\r
+::value[Simantics/Sequences/waitUntil, Simantics/Sequences/wait]\r
+    \r
+::value[Simantics/Sequences/waitCondition]\r
+\r
+## Parallel execution\r
+\r
+::value[Simantics/Sequences/fork, Simantics/Sequences/halt, Simantics/Sequences/stop]\r
+\r
+## Semantics\r
+\r
+Although the simulation sequences support threading, its semantics is deterministic. This is ensured by the following equivalences:\r
+\r
+    halt >> seqA                                       = halt\r
+    stop >> seqA                                       = stop\r
+    fork (execute actionA >> seqA) >> seqB             = execute actionA >> fork seqA >> seqB\r
+    fork (waitStep >> seqA) >> execute actionB >> seqB = execute actionB >> fork seqA >> seqB\r
+    fork (waitStep >> seqA) >> waitStep >> seqB        = waitStep >> fork seqA >> seqB\r
+    fork halt >> seqB                                  = seqB\r
+    fork seqA >> halt                                  = seqA\r
+    fork stop >> seqB                                  = stop\r
+    fork (waitStep >> seqA) >> stop                    = stop\r
+\r
+## Using the sequences with Apros\r
+\r
+In order to run the sequence in Apros, function \r
+\r
+::value[Apros/Sequences/runSequence]\r
+\r
+has been defined. It starts automatically starts simulation, if it is not yet running. When all simulation threads are halted or some thread calls `stop` the simulation is stopped. The sequence can also aborted by aborting the SCL-command (red box in the upper right corner of the console).\r
+\r
+    import "Apros/Sequences"\r
+    runSequence mdo\r
+        fork $ repeatForever mdo\r
+            waitCondition (getVar "TA01#TA11_LIQ_LEVEL" >= 3.0)\r
+            execute (setVar "BP01#PU11_SPEED_SET_POINT" 0.0)\r
+            wait 1\r
+        fork $ repeatForever mdo\r
+            waitCondition (getVar "TA01#TA11_LIQ_LEVEL" <= 2.0)\r
+            execute (setVar "BP01#PU11_SPEED_SET_POINT" 100.0)\r
+            wait 1\r
+\r
+## Examples\r
+\r
+Check that pressure of the point stays below a certain value:\r
+\r
+    fork mdo waitCondition (getVar "POINT1#PO11_PRESSURE" > 120.0)\r
+             execute (print "Error! Error!")\r
+             stop\r
+\r
+Check that the valve is closed 10 seconds after the operator presses the button:\r
+\r
+    fork $ repeatForever mdo\r
+        waitCondition (getVar "BUTTON#BINARY_VALUE")\r
+        fork mdo\r
+            wait 10\r
+            valvePos <- execute (getVar "VALVE#VA11_POSITION")\r
+            if valvePos == 0\r
+            then return () // OK\r
+            else mdo\r
+                execute (print "Error! Error!")\r
+                stop\r
+\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.02 (Exercise) Model fitting.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.02 (Exercise) Model fitting.md
new file mode 100644 (file)
index 0000000..d7602fd
--- /dev/null
@@ -0,0 +1,125 @@
+## Model fitting exercise\r
+\r
+### Step 1\r
+\r
+Create a diagram named X and run the following commands to create a simple model configuration:\r
+\r
+~~~\r
+aadd "X" "POINT" "PO1" (100,110)\r
+aadd "X" "POINT" "PO2" (140,110)\r
+aadd "X" "POINT" "PO3" (180,100)\r
+aadd "X" "POINT" "PO4" (180,120)\r
+aadd "X" "PIPE" "PI1" (120,110)\r
+aadd "X" "PIPE" "PI2" (160,100)\r
+aadd "X" "PIPE" "PI3" (160,120)\r
+amodi "PI1" "PI12_CONNECT_POINT_1" "PO1"\r
+amodi "PI1" "PI12_CONNECT_POINT_2" "PO2"\r
+amodi "PI2" "PI12_CONNECT_POINT_1" "PO2"\r
+amodi "PI2" "PI12_CONNECT_POINT_2" "PO3"\r
+amodi "PI3" "PI12_CONNECT_POINT_1" "PO2"\r
+amodi "PI3" "PI12_CONNECT_POINT_2" "PO4"\r
+aexclude "PO1"\r
+aexclude "PO3"\r
+aexclude "PO4"\r
+amodi "PI1" "PI12_AREA" 0.06\r
+amodi "PI2" "PI12_AREA" 0.03\r
+amodi "PI3" "PI12_AREA" 0.03\r
+amodi "ECCO" "MAXIMUM_TIME_STEP" 0.05\r
+amodi "ECCO" "CURRENT_TIME_STEP" 0.05\r
+amodi "SPEED" "SC_SPEED" 1000.0\r
+~~~\r
+\r
+Save the initial condition and set the simulation time to zero.\r
+\r
+### Step 2\r
+\r
+Run the following commands to print how mass flow of the\r
+pipe PI1 behaves in a simple transient.\r
+\r
+~~~\r
+loadInitialCondition (syncRead $ \_ -> fromResource $ relativeResource currentModel "/Initial%20Condition")\r
+runSequence mdo\r
+      execute (setVar "PO1#PO11_PRESSURE" 1.1)\r
+      fork (wait 1 >> stop)\r
+      fork $ repeatForever mdo\r
+          wait 0.05\r
+          execute do\r
+              massFlow = getVar "PI1#PI12_MIX_MASS_FLOW" :: Double\r
+              print massFlow\r
+~~~\r
+\r
+### Step 3\r
+\r
+Modify the above commands so that they print the index of the time step\r
+and variables PI1#PI12_MIX_MASS_FLOW, PI2#PI12_MIX_MASS_FLOW and PI3#PI12_MIX_MASS_FLOW.\r
+The commands should produce something like:\r
+\r
+~~~\r
+0 3.4978646673069216 1.728445205173922 1.728445205173922\r
+1 143.55517382976987 71.78198788751189 71.78198788751189\r
+2 261.95050765748715 130.97625819564252 130.97625819564252\r
+3 354.3858379588669 177.19356818048865 177.19356818048865\r
+...\r
+~~~\r
+\r
+Use the following functions to maintain the counter\r
+(although it is possible to compute it also from the current simulation time).\r
+\r
+::value[Prelude/ref, Prelude/getRef, Prelude/:=]\r
+\r
+### Step 4\r
+\r
+Modify the commands so that they compute the squared sum of errors from the "measurements" below:\r
+\r
+~~~\r
+measurements = [\r
+    [0.05, 3.4977860762417605, 1.7283740169550754, 1.7284367287300313],\r
+    [0.1, 134.88381983045093, 64.08353845423913, 70.80714606160574],\r
+    [0.15, 231.9062548984293, 105.65792385470164, 126.24691709056889],\r
+    [0.2, 296.4661748497294, 130.5064306373064, 165.95821168905044],\r
+    [0.25, 336.98201115920403, 144.68635329210002, 192.29464808262938],\r
+    [0.3, 361.56600347367186, 152.64673170010516, 208.9187479324867],\r
+    [0.35, 376.0973084183755, 157.07188101607773, 219.0252113124207],\r
+    [0.4, 384.690502383305, 159.57004084578205, 225.12040809039868],\r
+    [0.45, 389.742925383871, 160.98719663407357, 228.75573737254442],\r
+    [0.5, 392.7040735842458, 161.79511170873698, 230.90898615966157],\r
+    [0.55, 394.4365833534546, 162.2577698637119, 232.17883313521224],\r
+    [0.6, 395.36535200557034, 162.50160633728285, 232.86375430699712],\r
+    [0.65, 395.93996807514526, 162.65081127152007, 233.28915819466746],\r
+    [0.7, 396.2954901434386, 162.74229076331505, 233.55318938336018],\r
+    [0.75, 396.51546801100426, 162.79847242004152, 233.71697886953123],\r
+    [0.8, 396.65158867682203, 162.83302418223676, 233.81854447407886],\r
+    [0.85, 396.7358254901475, 162.85429827014457, 233.881506261103],\r
+    [0.9, 396.7879581657287, 162.8674097925786, 233.92052799957008],\r
+    [0.95, 396.8202241096274, 162.87549715428165, 233.94470806962704],\r
+    [1.0, 396.8401951361238, 162.88048891915273, 233.95968928259308]]\r
+~~~\r
+\r
+The columns of the data are, the simulation time\r
+PI1#PI12_MIX_MASS_FLOW, PI2#PI12_MIX_MASS_FLOW and PI3#PI12_MIX_MASS_FLOW.\r
+\r
+### Step 5\r
+\r
+Now create a function `objFun :: [Double] -> <Proc> Double` that is called as\r
+\r
+    objFun [1.0,1.1,1.2]\r
+    \r
+It should run the same commands as in previous steps and return the\r
+squared sum of errors, but additionally set\r
+PI1#PI12_LOSS_COEFF, PI2#PI12_LOSS_COEFF and PI3#PI12_LOSS_COEFF\r
+to the given values.\r
+\r
+It is good idea to also print the parameter values\r
+at the beginning of the function (and remove all other printing).\r
+\r
+### Step 6\r
+\r
+Use the function\r
+\r
+::value[Simantics/Newuoa/newuoa]\r
+\r
+to fit the loss coefficients to the measurements.\r
+Try first with small number of function evaluations,\r
+because the current implementation does not allow interrupting\r
+the optimization. You may try `rhobeg=1` and `rhoend=1e-4`\r
+and initial guess `[1,1,1]`.\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.03 (Exercise) Controller tuning.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.03 (Exercise) Controller tuning.md
new file mode 100644 (file)
index 0000000..abdfa8a
--- /dev/null
@@ -0,0 +1,46 @@
+## Controller tuning exercise\r
+\r
+### Step 1\r
+\r
+Load the model [ControllerTuning.apros](http://www.simantics.org/~niemisto/SCL20150513/ControllerTuning.apros).\r
+\r
+Run a sequence from SCL console that first sets the value of the set point (`SP01#SP_VALUE`) to 110,\r
+then waits 10 seconds and stops.\r
+\r
+::value[Apros/Sequences/runSequence,Simantics/Sequences/execute,Simantics/Sequences/setVar,Simantics/Sequences/wait,Simantics/Sequences/stop]\r
+\r
+Open the chart and examine the results.\r
+\r
+### Step 2\r
+\r
+Put your sequence inside a function that takes the controller parameters\r
+`PIC01#PI_GAIN` and `PIC01#PI_INTEGRATION_TIME` as a parameter and sets\r
+them at the same time with the set point. It should also load the IC\r
+before simulation with command\r
+\r
+    loadInitialCondition (syncRead $ \_ -> fromResource $ relativeResource currentModel "/Initial%20Condition")\r
+\r
+### Step 3\r
+\r
+Create a separate simulation thread that computes the last time the flow speed\r
+`XA01#ANALOG_VALUE` is within 1 from the set point value 110. Your function\r
+should return that value. The following functions are useful for that:   \r
+\r
+::value[Simantics/Sequences/getVar]\r
+::value[Simantics/Sequences/fork]\r
+::value[Prelude/repeatForever]\r
+\r
+### Step 4\r
+\r
+Try the optimization routine\r
+\r
+::value[Simantics/Newuoa/bobyqa]\r
+\r
+with function\r
+\r
+    f [x,y] = let dx=x-1 ; dy=y-2 in dx*dx + dy*dy\r
+\r
+### Step 5\r
+\r
+Optimize the controller parameters using the objective function you created in step 3.\r
+\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.04 (Solution) Model fitting.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.04 (Solution) Model fitting.md
new file mode 100644 (file)
index 0000000..01a762b
--- /dev/null
@@ -0,0 +1,46 @@
+## Model fitting solution\r
+\r
+The original loss coefficints are (although the optimizer will not find exact values)\r
+\r
+    amodi "PI1" "PI12_LOSS_COEFF" 1.2\r
+    amodi "PI2" "PI12_LOSS_COEFF" 4.6\r
+    amodi "PI3" "PI12_LOSS_COEFF" 2.2\r
+    \r
+Here is one possible solution:\r
+\r
+~~~\r
+import "Apros/Sequences"\r
+import "Apros/InitialCondition"\r
+import "Simantics/DB"\r
+import "Simantics/Model"\r
+\r
+objFun (p :: [Double]) = do\r
+    print p\r
+    loadInitialCondition (syncRead $ \_ -> fromResource $ relativeResource currentModel "/Initial%20Condition")\r
+    iRef = ref 0\r
+    sqSum = ref (0 :: Double)\r
+    runSequence mdo\r
+        execute do\r
+            setVar "PO1#PO11_PRESSURE" 1.1\r
+            setVar "PI1#PI12_LOSS_COEFF" (p!0)\r
+            setVar "PI2#PI12_LOSS_COEFF" (p!1)\r
+            setVar "PI3#PI12_LOSS_COEFF" (p!2)\r
+        fork (wait 1 >> stop)\r
+        fork $ repeatForever mdo\r
+          wait 0.05\r
+          execute do\r
+              i = getRef iRef\r
+              iRef := i+1\r
+              row = measurements!i\r
+              a = getVar "PI1#PI12_MIX_MASS_FLOW" - row!1 :: Double\r
+              b = getVar "PI2#PI12_MIX_MASS_FLOW" - row!2 :: Double\r
+              c = getVar "PI3#PI12_MIX_MASS_FLOW" - row!3 :: Double\r
+              sqSum := getRef sqSum + a*a + b*b + c*c\r
+    getRef sqSum\r
+~~~\r
+\r
+with this definition call\r
+\r
+    newuoa 1.0 1e-4 100 objFun [1,1,1]\r
+    \r
+from console.
\ No newline at end of file
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/4.01 Other language features.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/4.01 Other language features.md
new file mode 100644 (file)
index 0000000..39ddf64
--- /dev/null
@@ -0,0 +1,79 @@
+## Importing functionality from Java\r
+\r
+Java interfaces and classes can be imported from Java by declaring them inside `importJava` block:\r
+\r
+~~~\r
+importJava "java.util.regex.Pattern" where\r
+    data Pattern\r
+\r
+importJava "java.util.List" where\r
+    data List a\r
+~~~\r
+\r
+Java methods, constructors and fields can be similarly imported by giving\r
+their type annotations in `importJava` block:\r
+\r
+~~~\r
+importJava "java.util.regex.Pattern.compile" where\r
+    @JavaName compile\r
+    compilePattern :: String -> Pattern\r
+\r
+    @JavaName matcher\r
+    createMatcher :: Pattern -> String -> <Proc> Matcher\r
+\r
+importJava "java.util.regex.Matcher" where\r
+    data Matcher\r
+\r
+    @JavaName matches\r
+    matcherMatches :: Matcher -> <Proc> Boolean\r
+\r
+matches : Pattern -> String -> <Proc> Boolean\r
+matches pattern text = do\r
+    matcherMatches (createMatcher pattern text)\r
+~~~\r
+\r
+Another example:\r
+\r
+~~~\r
+importJava "java.util.ArrayList" where\r
+    @JavaName "<init>"\r
+    createArrayList :: () -> <Proc> List a\r
+\r
+    @JavaName "<init>"\r
+    createArrayListWithCapacity :: Integer -> <Proc> List a\r
+\r
+    @JavaName size\r
+    sizeList :: List a -> <Proc> Integer\r
+\r
+    @JavaName get\r
+    getList :: List a -> Integer -> <Proc> a\r
+\r
+    @JavaName set\r
+    setList :: List a -> Integer -> a -> <Proc> ()\r
+\r
+    @JavaName add\r
+    addList :: List a -> a -> <Proc> Boolean\r
+~~~\r
+\r
+Java constructor is referred with `"<init>"`. If Java method name and SCL name matches the annotation `@JavaName`\r
+can be left out. Java import mechanism tries to be quite flexible. It provides some arguments based on the effects\r
+the function has. It also ignores the return value of the Java method if the return type is `()` in SCL. \r
+\r
+A major functionality currently still missing is the ability to create new implementations of existing Java interfaces\r
+in SCL code or extend an existing class. This can be worked around currently by writing new implementations in Java.\r
+\r
+## Relational sublanguage \r
+\r
+* Select, when, enforce\r
+* Transformations\r
+\r
+## Other language features\r
+\r
+* Defining data types\r
+* Defining type classes\r
+* Defining effects \r
+* Restricted imports\r
+* Documentation strings\r
+* Private definitions\r
+* Binary operator precedence\r
+\r
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/X Old tutorial.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/X Old tutorial.md
new file mode 100644 (file)
index 0000000..68baf45
--- /dev/null
@@ -0,0 +1,1698 @@
+<script type="text/javascript"\r
+  src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">\r
+</script>\r
+\r
+# Getting started\r
+\r
+SCL Console is the easiest way to access SCL in Simantics. Therefore we will\r
+be using it all the time in this tutorial.  \r
+\r
+----\r
+\r
+SCL Console is opened from the menu *Show View/Other/SCL Console*.\r
+\r
+\includegraphics[scale=0.4]{figures/ShowView.png}\r
+\hspace{1cm}\r
+\includegraphics[scale=0.4]{figures/ShowView2.png}\r
+\r
+The view that is opened looks like this:\r
+\r
+\includegraphics[scale=0.5]{figures/SCLConsole.png}\r
+\r
+SCL commands are written to the box at the bottom of the view and the command responses\r
+are shown in the upper part of the view. Try writing\r
+~~~\r
+> 1 + 1\r
+~~~\r
+and press enter.\r
+\r
+\r
+----\r
+If the current command in the SCL Console input box contains an error, it is shown with a red underline.\r
+Moving the mouse pointer to that position shows an error description:\r
+\r
+\includegraphics[scale=0.5]{figures/ConsoleError.png}\r
+\r
+When the command contains an errors, the console is not willing to execute it. Pressing *enter*\r
+adds a new line to the command.\r
+\r
+While editing the command, arrow keys can be used to move the cursor around. \r
+Pressing *ctrl-enter* adds a new line even if the command is currently valid.\r
+Pressing *ctrl* and arrow keys up or down, you can browse the previously entered commands. \r
+\r
+Also copy *ctrl-C*, paste and cut work in the editing area.\r
+\r
+\r
+----\r
+### Exercise\r
+\r
+Run a multiline command:\r
+~~~\r
+> for [1..10] (\x -> \r
+      for [1..x] (\y ->\r
+          print (show x + " + " + show y + " = " + show (x+y))\r
+      )\r
+  )   \r
+~~~\r
+Then find it from the history and modify it to show multiplications instead of additions.\r
+\r
+\r
+----\r
+### Remark\r
+We will show lots of examples of SCL code in this tutorial. If some explanation leaves\r
+you in uncertain state, copy some of the examples to the console and \r
+play with them.\r
+\r
+\r
+## Basic expressions\r
+\r
+We start from the basic mathematical expressions you can write in SCL.\r
+This should cover the most needs you have if you want to use SCL expressions\r
+in component types.\r
+\r
+----\r
+Writing mathematical formulas in SCL is mostly unsurprising.\r
+~~~\r
+> 3*7+1\r
+22\r
+> 2 - sqrt 2\r
+0.5857864376269049\r
+> cos pi\r
+-1.0\r
+~~~\r
+\r
+One difference from many programming languages is that parentheses are not required around the \r
+parameters and multiple parameters are separated by whitespace:\r
+~~~\r
+> atan2 1 1\r
+0.7853981633974483\r
+~~~\r
+\r
+Parentheses are needed for each parameter separately, if the parameter is\r
+more complicated expression than  constant or variable:\r
+~~~\r
+> atan2 (sin 0.4) (cos 0.4)\r
+0.4\r
+~~~\r
+\r
+\r
+----\r
+### Exercise\r
+What is wrong with the following code. How to fix it?\r
+~~~\r
+> sin -1\r
+~~~\r
+\r
+----\r
+The results of the computations can be bound to variables and used in subsequent expressions:\r
+~~~\r
+> m = 4.0\r
+> c = 2.998e8\r
+> energy = m * c^2\r
+> energy\r
+3.5952016E17\r
+~~~\r
+\r
+If the variable is bound multiple times, the latest definition is used:\r
+~~~\r
+> a = 4\r
+> a = 8\r
+> a\r
+8\r
+~~~\r
+\r
+\r
+----\r
+### Remark\r
+Replacing a variable binding with a new binding is a feature of SCL Console.\r
+In SCL modules, variables can be bound only once.\r
+\r
+----\r
+A variable name must begin with a *lower-case* letter or an underscore.\r
+Following that can be any number of letters (lower-case and upper-case), numbers and underscores.\r
+The following names are reserved and cannot be used as identifiers:\r
+`_`, `forall`, `if`, `then`, `else`,\r
+`where`, `by`, `do`, `mdo`, `class`, `effect`,\r
+`match`, `with`, `instance`, `deriving`,\r
+`data`, `type`, `infix`, `infixl`, `infixr`.\r
+`import`, `include`, `importJava`, `as`.\r
+\r
+\r
+----\r
+\r
+This is the list of arithmetical functions available in SCL. The middle column\r
+contains the types of the functions. You can ignore them now.\r
+\r
+<table><tr><td>\r
+zero </td><td> Additive a => a </td><td> additive neutral element </td></tr><tr><td> \r
+(+) </td><td> Additive a => a -> a -> a </td><td> addition </td></tr><tr><td>\r
+sum </td><td> Additive a => [a] -> a </td><td> sum of list elements </td></tr><tr><td>\r
+neg </td><td> Ring a => a -> a </td><td> negation </td></tr><tr><td>\r
+(-) </td><td> Ring a => a -> a -> a </td><td> difference </td></tr><tr><td>\r
+one </td><td> Ring a => a </td><td> multiplicative neutral element </td></tr><tr><td>\r
+(*) </td><td> Ring a => a -> a -> a </td><td> multiplication </td></tr><tr><td>\r
+fromInteger </td><td> Ring a => Integer -> a </td><td> converts an integer to another number format </td></tr><tr><td>\r
+abs </td><td> OrderedRing a => a -> a </td><td> absolute value </td></tr><tr><td>\r
+(/) </td><td> Real a => a -> a -> a </td><td> division </td></tr><tr><td>\r
+(`^`) </td><td> Real a => a -> a -> a </td><td> exponentiation </td></tr><tr><td>\r
+pi </td><td> Real a => a </td><td> $\pi$ </td></tr><tr><td>\r
+sqrt </td><td> Real a => a -> a </td><td> square root </td></tr><tr><td>\r
+exp </td><td> Real a => a -> a </td><td> exponent function </td></tr><tr><td>\r
+log </td><td> Real a => a -> a </td><td> natural logarithm </td></tr><tr><td>\r
+sin,cos,tan </td><td> Real a => a -> a </td><td> trigonometric functions </td></tr><tr><td>\r
+asin,acos,atan </td><td> Real a => a -> a </td><td> inverse trigonometric functions </td></tr><tr><td>\r
+atan2 </td><td> Real a => a -> a -> a </td><td> arctangent with two parameters </td></tr><tr><td>\r
+sinh,cosh,tanh </td><td> Real a => a -> a </td><td> hyperbolic functions </td></tr><tr><td>\r
+asinh,acosh,atanh </td><td> Real a => a -> a </td><td> inverse hyperbolic functions </td></tr><tr><td>\r
+fromDouble </td><td> Real a => Double -> a </td><td> converts a double to another number format </td></tr><tr><td>\r
+floor </td><td> Real a => a -> a </td><td> the largest previous integer </td></tr><tr><td>\r
+ceil </td><td> Real a => a -> a </td><td> the smallest following integer </td></tr><tr><td>  \r
+div </td><td> Integer a => a -> a -> a </td><td> integer division </td></tr><tr><td>\r
+mod </td><td> Integer a => a -> a -> a </td><td> integer remainer\r
+</td></tr></table>\r
+\r
+Their meaning is mostly self-explanatory. \r
+Real and integer divisions are two different functions:\r
+~~~\r
+> 5 / 2\r
+2.5\r
+> 5 `div` 2\r
+2\r
+~~~\r
+The hat `^` is exponentiation:\r
+~~~\r
+> 3^4\r
+81.0\r
+~~~ \r
+Negation function `neg` can be used with the unary minus syntax. So the following are equivalent:\r
+~~~\r
+> neg 3\r
+-3\r
+> -3\r
+-3\r
+~~~\r
+\r
+\r
+----\r
+### Remark\r
+At this point you may encounter the following problem:\r
+~~~\r
+> a = 2\r
+> b = 3.4\r
+> a + b\r
+~~~\r
+The console does not execute the last expression because it contains an error \r
+``Expected $\langle$Integer$\rangle$ got $\langle$Double$\rangle$''.\r
+This is because the variable `a` is bound to an integer value and `b` is bound to a double value\r
+and SCL does automatic number conversion only for numerical literals (2, 3.4 etc.). There are several ways to fix\r
+the problem. First is to define `a` as a double:\r
+~~~\r
+> a = 2.0\r
+~~~\r
+or\r
+~~~\r
+> a = 2 :: Double\r
+~~~\r
+Another way is to convert the integer value to double in the final expression:\r
+~~~\r
+> fromInteger a + b\r
+5.4\r
+~~~\r
+\r
+\r
+----\r
+\r
+Numbers and many other objects can be compared with the following functions:\r
+<table><tr><td>\r
+(==) </td><td> Eq a => a -> a -> Boolean </td><td> equality </td></tr><tr><td> \r
+(!=) </td><td> Eq a => a -> a -> Boolean </td><td> inequality </td></tr><tr><td>\r
+(<),(>) </td><td> Ord a => a -> a -> Boolean </td><td> strict comparison </td></tr><tr><td>\r
+(<=),(>=) </td><td> Ord a => a -> a -> Boolean </td><td> non-strict comparison </td></tr><tr><td>\r
+min </td><td> Ord a => a -> a -> a </td><td> returns the the smaller of two parameters </td></tr><tr><td>\r
+max </td><td> Ord a => a -> a -> a </td><td> returns the larger of two parameters </td></tr><tr><td>\r
+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
+</td></tr></table>\r
+For example:\r
+\r
+~~~\r
+> 1 < 2\r
+True\r
+> 6 < 4\r
+False\r
+> max 1.5 3.8\r
+3.8\r
+~~~\r
+\r
+\r
+----\r
+Boolean expressions can be used to write conditional expressions:\r
+~~~\r
+> a = 3\r
+> b = 4\r
+> if a < b then a else b\r
+3\r
+> a = 5\r
+> if a < b then a else b\r
+4\r
+~~~\r
+In order to test multiple conditions, if-expressions can be combined:\r
+~~~\r
+> if a < b \r
+  then -1\r
+  else if a > b\r
+  then 1\r
+  else 0\r
+1\r
+~~~\r
+\r
+\r
+----\r
+Boolean values can be combined with conjunction `&&`, disjunction `||` and negation `not`.\r
+~~~\r
+> True && False\r
+False\r
+> True || False\r
+True\r
+> not True\r
+False\r
+~~~\r
+\r
+\r
+----\r
+\r
+Strings are written by enclosing them into double quotes:\r
+~~~\r
+> "Hello world!"\r
+"Hello world!"\r
+~~~\r
+\r
+Some of the operators seen so far can also be applied to strings:\r
+~~~\r
+> "Hello" + " world!"\r
+"Hello world!"\r
+> "Foo" < "Bar"\r
+False\r
+~~~\r
+\r
+There are also many functions specific to strings. We will however \r
+describe just some of them:\r
+<table><tr><td>\r
+length </td><td> String -> Integer </td><td> the length of a string </td></tr><tr><td>\r
+substring </td><td> String -> Integer -> Integer -> String </td><td> returns a substring of the string\r
+                                                     when the begin and the end positions of the\r
+                                                     string are given </td></tr><tr><td>\r
+show </td><td> Show a => a -> String </td><td> converts a value to a string </td></tr><tr><td> \r
+read </td><td> Read a => String -> a </td><td> converts a string to a value </td></tr><tr><td>\r
+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
+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
+startsWith </td><td> String -> String -> Boolean </td><td> checks if the string starts with the given prefix </td></tr><tr><td>\r
+trim </td><td> String -> String </td><td> removes the white space from the beginning and end of the string\r
+</td></tr></table>\r
+From these functions, we need only `show` in this tutorial. \r
+\r
+~~~\r
+> x = 5.7\r
+> "x = " + show x\r
+x = 5.7\r
+~~~\r
+\r
+\r
+## Functions\r
+\r
+In SCL, functions are first-class values that can be manipulated with the\r
+same ease as numbers and other values. Almost all control structures also\r
+require that you define your own functions. Therefore we describe them\r
+before going to other data structures.\r
+\r
+----\r
+The syntax of the function definitions in SCL resemble function definitions in mathematics:\r
+~~~\r
+> dist x y = abs (x - y)\r
+> dist 2 5\r
+3\r
+> dist 6 4\r
+2\r
+~~~\r
+\r
+\r
+----\r
+### Exercise\r
+Define a generalized average function:\r
+$${\rm avgG}\ p\ x\ y = \left({x^p + y^p \over 2}\right)^{1 \over p}$$\r
+Check that it works correctly:\r
+~~~\r
+> avgG 1 3 5\r
+4.0\r
+> avgG 2 2 14\r
+10.0\r
+> avgG (-1) 3 6\r
+4.0\r
+~~~\r
+\r
+\r
+----\r
+\r
+Functions can be recursive. For example Euclid's algorithm for\r
+computing greatest common divisor for two integers can be implemented\r
+as:\r
+~~~\r
+> gcd a b = if a > b\r
+            then gcd b a\r
+            else if a == 0\r
+            then b\r
+            else gcd (b `mod` a) a\r
+> gcd 12 9\r
+3           \r
+~~~\r
+\r
+\r
+----\r
+### Exercise\r
+Implement a function `fib` for computing Fibonacci numbers. First two Fibonacci numbers\r
+are one and after that every Fibonacci number is the sum of two previous Fibonacci numbers:\r
+1, 1, 2, 3, 5, 8, 13, \ldots.  \r
+\r
+\r
+----\r
+Many functions are implemented by cases. In these situations function definition can be\r
+written as multiple separate equations:\r
+~~~\r
+> gcd a b | a > b = gcd b a\r
+  gcd 0 b         = b\r
+  gcd a b         = gcd (b `mod` a) a\r
+~~~\r
+In this way it is easier to verify that every individual equation is corrent.\r
+\r
+There are two ways to restrict the applicability of an equation.\r
+The first way is to use patterns as parameters instead of just variables.\r
+In the example above, the second equation has a constant pattern 0 as a first parameter.\r
+We see later more complicated patterns.\r
+The second way to restrict the applicability is to add guards to the equation. \r
+A guard is the part in the first equation above after the vertical bar and before the equality.\r
+It is a boolean condition that must be true for equation to be applicable.\r
+\r
+The actual function value is computed by the first equation that can be applied with the given parameters. \r
+\r
+\r
+----\r
+### Exercise\r
+Rewrite the Fibonacci's function using either constant patterns or guards.\r
+\r
+\r
+----\r
+One of the cornerstones of all functional programming languages, including SCL, is the ability\r
+to give functions as parameters to other functions:\r
+~~~\r
+> epsilon = 1e-9\r
+> der f x = (f (x + epsilon) - f (x - epsilon)) / (2*epsilon)\r
+> der sin 0\r
+1.0\r
+> der log 5\r
+0.2000000165480742\r
+~~~\r
+This kind of functions are called *higher order functions*.\r
+\r
+Here is another example:\r
+~~~\r
+> iterate f n x | n > 0     = iterate f (n-1) (f x)\r
+                | otherwise = x\r
+> collatz n | n `mod` 2 == 0 = n `div` 2\r
+            | otherwise      = 3*n + 1\r
+> iterate collatz 0 13\r
+13\r
+> iterate collatz 1 13\r
+40\r
+> iterate collatz 2 13\r
+20\r
+> iterate collatz 5 13\r
+16\r
+> iterate collatz 8 13\r
+2\r
+> iterate collatz 9 13\r
+1\r
+~~~\r
+\r
+\r
+----\r
+Often the function we want to define can be get by filling some parameters of an already existing function.\r
+For example a function `limitZero`, that returns zero if its parameter is negative and otherwise\r
+returns the parameter unmodified, can be defined as:\r
+~~~\r
+> limitZero = max 0.0\r
+> limitZero 2.1\r
+2.1\r
+> limitZero (-5.4)\r
+0.0\r
+~~~\r
+This is called *partial application*.\r
+\r
+\r
+----\r
+Binary operators can be referred and partially applied by enclosing them\r
+in parenthesis:\r
+~~~\r
+> f = (+)\r
+> f 1 2\r
+3\r
+> incByOne = (+) 1\r
+> incByOne 5\r
+6\r
+~~~\r
+\r
+Inversely, an ordinary function can be used as a binary operator by enclosing it\r
+to backquotes (in fact, we have seen it already in the definiton of `gcd`):\r
+~~~\r
+> 1 `f` 2\r
+3\r
+> 14 `div` 3\r
+4\r
+~~~\r
+\r
+\r
+----\r
+Functions can be also defined without giving them a name:\r
+~~~\r
+> \x -> x * 2\r
+<function>\r
+> (\x -> x * 2) 3\r
+6\r
+~~~\r
+\r
+This is useful when using higher order functions:\r
+~~~\r
+> der (\x -> x^2 - 5*x) 2\r
+-1.000000082740371\r
+~~~\r
+\r
+\r
+----\r
+For writing complex functions, it is necessary to define auxiliary\r
+variables. There are two ways of doing this in SCL. The first way is\r
+`where` syntax:\r
+~~~\r
+> dist x1 y1 x2 y2 = sqrt (dx*dx + dy*dy)\r
+    where\r
+      dx = x1-x2\r
+      dy = y1-y2      \r
+~~~\r
+The second way is `do` syntax\r
+~~~\r
+> dist x1 y1 x2 y2 = do\r
+      dx = x1-x2\r
+      dy = y1-y2\r
+      sqrt (dx*dx + dy*dy)      \r
+~~~\r
+The difference between these constructs is often only aesthetic.\r
+\r
+One feature of SCL that is imporant here is that SCL uses\r
+the layout (indentation) of the code for parsing. The statements\r
+in the same `where` or `do` block must be consistently\r
+indented and indentation must be larger than the enclosing context.\r
+\r
+\r
+----\r
+\r
+SCL standard library defines the following functions for\r
+manipulating functions:\r
+<table><tr><td>\r
+id </td><td> a -> a </td><td> identity function </td></tr><tr><td>\r
+(\$) </td><td> (a -> <e> b) -> a -> <e> b </td><td> application operator </td></tr><tr><td>\r
+(.) </td><td> (b -> <e> c) -> (a -> <e> b) -> (a -> <e> c) </td><td> function composition </td></tr><tr><td>\r
+const </td><td> a -> b -> a </td><td> constant function </td></tr><tr><td>\r
+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
+uncurry </td><td> (a -> b -> <e> c) -> ((a, b) -> <e> c)  </td><td> inverse of curry </td></tr><tr><td>\r
+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
+uncurry3 </td><td> (a -> b -> c -> <e> d) -> ((a, b, c) -> <e> d) </td><td> inverse of curry3  </td></tr><tr><td>\r
+flip </td><td> (a -> b -> <e> c) -> b -> a -> <e> c </td><td> flips the order of the function parameters\r
+</td></tr></table>\r
+Function `$` just applies given function and a parameter:\r
+\r
+~~~\r
+f $ x = f x\r
+~~~\r
+\r
+The precedence of the operator is very weak and it associates\r
+to right. It can be used\r
+to remove some parentheses in deeply nested expression. So\r
+we can write\r
+\r
+~~~\r
+> text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."\r
+> length \r
+    $ filter (\s -> length s > 4) \r
+    $ splitString text "[ ,.]"\r
+5\r
+~~~\r
+\r
+instead of\r
+\r
+~~~\r
+> length (filter (\s -> length s > 4) (splitString text "[ ,.]"))\r
+5\r
+~~~\r
+\r
+\r
+## Data structures\r
+\r
+----\r
+One of the simplest data structure is a pair:\r
+~~~\r
+> ("Citizen Kane", 1941)\r
+("Citizen Kane", 1941)\r
+~~~\r
+As seen above, the different elements of the pair can have different types. \r
+\r
+The components of the pair can be accessed with the functions `fst` and `snd`:\r
+~~~\r
+> fst ("Citizen Kane", 1941)\r
+"Citizen Kane"\r
+> snd ("Citizen Kane", 1941)\r
+1941\r
+~~~\r
+\r
+Other tuple lenghts are also supported:\r
+~~~\r
+> ()\r
+()\r
+> ("1", 1, 1.0)\r
+("1", 1, 1.0)\r
+~~~\r
+\r
+\r
+----\r
+Pairs and other tuples are useful, when we want to return more than one value from a function:\r
+~~~\r
+> toPolarCoordinates (x,y) = (sqrt (x*x + y*y), atan2 y x)\r
+> toRectangularCoordinates (r,angle) = (r*cos angle, r*sin angle)\r
+> polar = toPolarCoordinates (3,-6)\r
+> polar\r
+(6.708203932499369, -1.1071487177940904)\r
+> toRectangularCoordinates polar\r
+(3.000000000000001, -6.0)\r
+~~~\r
+\r
+As seen in the above example, when tuples are given as parameters to the functions, they can\r
+be pattern matched. In `toPolarCoordinates (x,y)` the components of the pair given\r
+as a parameter to the function are bound to `x` and `y`. \r
+A much less readable version of the above function would be:\r
+~~~\r
+> toPolarCoordinates p = (sqrt (fst p*fst p + snd p*snd p), \r
+                          atan2 (snd p) (fst p))\r
+~~~\r
+\r
+Patterns can be nested. A nonsensical example: \r
+~~~\r
+> shuffle ((a,b), (c,d)) = ((c,b), (a,d))\r
+> shuffle ((1,2), (3,4))\r
+((3, 2), (1, 4))\r
+~~~\r
+\r
+\r
+----\r
+### Remark\r
+The following command produces an error ``Expected $\langle$Integer$\rangle$ got $\langle$String$\rangle$\r
+~~~\r
+> shuffle (("1","2"), ("3","4"))\r
+~~~\r
+althought the function definition doesn't seem to care about the contents of the values (even if they are all of different types).\r
+This is a restriction of the current version of SCL Console: all functions you define are *monomorphic* meaning\r
+that all types involved must be fully known. When this is not a case, the compiler chooses the types somewhat arbitrarily.\r
+In SCL modules, there is no such restrictions and the compiler chooses the most generic type as possible for a function.\r
+Therefore, if the `shuffle` were defined in a SCL module, the above command would work.\r
+\r
+----\r
+Maybe the most important datatype is a list that may \r
+hold any number of values of the same type. Lists\r
+are constructed by enclosing the values in brackets:  \r
+~~~\r
+> [1, 2, 3, 4]\r
+[1, 2, 3, 4]\r
+~~~\r
+\r
+Elements of the lists are accessed with `!` operator:\r
+~~~\r
+> l = [1, 2, 3]\r
+> l!0\r
+1\r
+> l!2\r
+3\r
+~~~\r
+The length of the list can be found out with `length`:\r
+~~~\r
+> length l\r
+3\r
+~~~\r
+\r
+Two lists are joined together with `+` operator:\r
+~~~\r
+> [1, 2] + [3, 4]\r
+[1, 2, 3, 4]\r
+~~~\r
+\r
+Finally, a list containing some range of integers can be constructed as\r
+~~~\r
+> [4..9]\r
+[4, 5, 6, 7, 8, 9]\r
+~~~\r
+\r
+\r
+----\r
+### Exercise\r
+A quadratic equation $a x^2 + b x + c = 0$ has real solutions only if the discriminant\r
+$\Delta = b^2 - 4ac$ is non-negative. If it is zero, the equation has one solution and\r
+if it is positive, the equation has two solutions:\r
+$${-b \pm \sqrt{\Delta} \over 2a}.$$\r
+Write a function $`solveQuadratic`$ that solves a quadratic function whose\r
+coefficients are given as parameters and returns a list containing all solutions\r
+of the equation:\r
+~~~\r
+> solveQuadratic 1 1 (-2)\r
+[1.0, -2.0]\r
+> solveQuadratic 1 1 1\r
+[]\r
+~~~\r
+\r
+\r
+----\r
+Many useful tools for manipulating lists are higher order functions.\r
+The function `map` applies a given function to all elements of a list\r
+and produces a new list of the same length from the results:\r
+$$`map`\ f\ [x_1,x_2,\ldots,x_n] = [f\ x_1,f\ x_2,\ldots,f\ x_n]$$\r
+Here is couple of examples:\r
+~~~\r
+> map (\s -> "_" + s + "_") ["a", "b", "c"]\r
+["_a_", "_b_", "_c_"]\r
+> map ((*) 3) [1..4]\r
+[3, 6, 9, 12]\r
+~~~\r
+\r
+Unwanted elements can be removed from a list by `filter` function:\r
+~~~\r
+> filter (\s -> length s > 4) ["small", "big", "large", "tiny"]\r
+["small", "large"]\r
+> isPrime p = filter (\d -> p `mod` d == 0) [2..p-1] == []\r
+> filter isPrime [2..20]\r
+[2, 3, 5, 7, 11, 13, 17, 19]\r
+~~~\r
+\r
+The function `foldl` computes an aggergate value over a list of values\r
+by applying a binary function to the elements starting from the given initial element:\r
+$${\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
+In practice:\r
+~~~\r
+> foldl (+) 0 [2,3,4]\r
+9\r
+> foldl (*) 1 [2,3,4]\r
+24\r
+> foldl max 0 [2,3,4]\r
+4\r
+~~~\r
+The function `sum` is equivalent to `foldl (+) zero`, but is in \r
+some cases implemented much more effeciently (for example for strings).\r
+\r
+The function `concatMap` is similar to `map`, but it assumes\r
+that the given function produces lists and concatenates the lists together:\r
+~~~\r
+> concatMap \r
+      (\(n,v) -> map (const v) [1..n]) \r
+      [(3,"a"), (2,"l"), (1,"i")]\r
+["a", "a", "a", "l", "l", "i"]\r
+~~~\r
+\r
+\r
+----\r
+### Exercise\r
+Define a generalized average function for lists:\r
+$${\rm avgG}\ p\ [x_1,\ldots,x_{n}] = \left({x_1^p + \cdots + x_n^p \over n}\right)^{1 \over p}$$\r
+\r
+\r
+----\r
+### Exercise\r
+One useful way for producing lists is to map a range expression. For example\r
+~~~\r
+> diffs (l :: [Integer]) = map (\i -> l!(i+1) - l!i) [0..length l-2]\r
+> diffs [1,2,4,8,3]\r
+[1, 2, 4, -5]\r
+~~~\r
+Use the pattern to reimplement the function `reverse` from the standard library\r
+that reverses the order of elements in a list.\r
+\r
+\r
+----\r
+SCL supports *list comprehension* which allows to write\r
+many list producing expressions with a syntax that closely\r
+resembles the set comprehension from mathematics:\r
+~~~\r
+> l = [1..3]\r
+> [2*x | x <- l]\r
+[2, 4, 6]\r
+> [(x,y) | x <- l, y <- l]\r
+[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]\r
+> [(x,y) | x <- l, y <- l, x < y]\r
+[(1, 2), (1, 3), (2, 3)]\r
+> [(x,y) | x <- l, y=4-x]\r
+[(1, 3), (2, 2), (3, 1)]\r
+~~~\r
+As seen in the above examples, the left side of the vertical bar \r
+can be any expression producing the elements of the list. The\r
+right side of the bar is a list of producing statements:\r
+`x <- l` considers all `x` in the list `l`,\r
+`x = e` sets the value of `x` by the expression `e`\r
+and any boolean expression like `x < y` filters the produced elements.\r
+\r
+\r
+----\r
+### Remark\r
+SCL does not support yet pattern matching of lists althought it is supported in Haskell. \r
+\r
+\r
+----\r
+This is a list of some list functions provided by SCL standard library:\r
+\r
+\r
+<table><tr><td>\r
+map </td><td> Functor a => (a -> b) -> f a -> f b </td><td> </td></tr><tr><td>\r
+concatMap </td><td> (a -> <e> [b]) -> [a] -> <e> [b] </td><td> </td></tr><tr><td>\r
+filter </td><td> (a -> <e> Boolean) -> [a] -> <e> [a] </td><td> </td></tr><tr><td>\r
+filterJust </td><td> [Maybe a] -> [a] </td><td> </td></tr><tr><td>\r
+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
+foldl1 </td><td> (a -> a -> <e> a) -> [a] -> <e> a </td><td> </td></tr><tr><td>\r
+unfoldl </td><td> (b -> <e> Maybe (a, b)) -> b -> <e> [a] </td><td> </td></tr><tr><td>\r
+unfoldr </td><td> (b -> <e> Maybe (a, b)) -> b -> <e> [a] </td><td> </td></tr><tr><td>\r
+zip </td><td> [a] -> [b] -> [(a,b)] </td><td> combine elements in the two lists </td></tr><tr><td>\r
+zipWith </td><td> (a -> b -> <e> c) -> [a] -> [b] -> <e> [c] </td><td> </td></tr><tr><td>\r
+unzip </td><td> [(a,b)] -> ([a],[b]) </td><td> </td></tr><tr><td>\r
+sort </td><td> Ord a => [a] -> [a] </td><td> sorts the elements in the list </td></tr><tr><td>\r
+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
+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
+(\\) </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
+range </td><td> Integer -> Integer -> [Integer] </td><td> </td></tr><tr><td>\r
+reverse </td><td> [a] -> [a] </td><td> reverses the order of the elements in the list </td></tr><tr><td>\r
+take </td><td> Integer -> [a] -> [a] </td><td> returns $n$ first elements of the list </td></tr><tr><td>\r
+drop </td><td> Integer -> [a] -> [a] </td><td> removes $n$ first elements from the list and returns the tail </td></tr><tr><td>\r
+lookup </td><td>  Eq a => a -> [(a, b)] -> Maybe b </td><td> finds a pair from the list such that the first component\r
+                                             matches the given value and returns the second component </td></tr><tr><td>\r
+and </td><td> [Boolean] -> Boolean </td><td> </td></tr><tr><td>\r
+or </td><td> [Boolean] -> Boolean </td><td> </td></tr><tr><td>\r
+any </td><td> (a -> <e> Boolean) -> [a] -> <e> Boolean </td><td> </td></tr><tr><td>\r
+all </td><td> (a -> <e> Boolean) -> [a] -> <e> Boolean \r
+</td></tr></table>\r
+\r
+\r
+----\r
+One data structure used quite often is an optional value.\r
+It is useful, if the function produces the result only for\r
+some parameter values. Optional value is either \r
+`Just value` or `Nothing`. Here is an example:\r
+~~~\r
+> safeSqrt x | x >= 0    = Just (sqrt x)\r
+             | otherwise = Nothing\r
+> safeSqrt 2\r
+Just 1.4142135623730951\r
+> safeSqrt (-2)\r
+Nothing   \r
+~~~\r
+The type of the expressions  `Just value` and `Nothing` is `Maybe t`,\r
+where $`t`$ is the type of `value`.\r
+\r
+Optional values can be handled with pattern matching\r
+(the example is from the standard library):\r
+~~~\r
+> fromMaybe _ (Just value)  = value\r
+  fromMaybe default Nothing = default\r
+~~~\r
+\r
+\r
+----\r
+Sometimes it is useful to use pattern matching without\r
+defining a new function for it. Therefore there is\r
+`match` construct:\r
+~~~\r
+> match (1,2,3) with\r
+     (x,y,z) -> x+y+z\r
+6\r
+~~~\r
+As with functions, there can be multiple cases and the\r
+first matching case is chosen:\r
+~~~\r
+> match safeSqrt 3 with\r
+      Just v  -> v\r
+      Nothing -> fail "Something bad happened." \r
+~~~\r
+\r
+## Types\r
+\r
+----\r
+\r
+Every expression in SCL has a type. Type determines the set of possible values\r
+of the expression. They are used for detecting errors in SCL code, for choosing the\r
+right implementation of a method (for example addition `(+)`) and for generating\r
+efficient byte code.\r
+\r
+When the type is monomorphic (does not contain type variables), it can be printed as\r
+~~~\r
+> typeOf "foo"\r
+String\r
+> typeOf [1,2,3]\r
+[Integer]\r
+~~~\r
\r
+\r
+----\r
+Normally SCL compiler will infer the types of the expressions automatically and\r
+you don't have to specify them manually. There are however situations where\r
+explicit control of types is useful:\r
+* You want to document the interface of your functions. It is good practice\r
+  to write a type annotation for all top-level functions declared in a SCL module.\r
+  Such declarations are not available in SCL Console: \r
+  ~~~\r
+  fst :: (a,b) -> a\r
+  fst (x,y) = x\r
+  ~~~\r
+* SCL compiler cannot infer a type that satisfies all the required constraints:\r
+  ~~~\r
+  > strId x = show (read x)\r
+  There is no instance for <Show ?a>.\r
+  There is no instance for <Read ?a>.\r
+  > strId x = show (read x :: Integer)\r
+  > strId "1"\r
+  "1"\r
+  > strId "1.0"\r
+  java.lang.NumberFormatException: For input string: "1.0"\r
+  ...\r
+  > strId x = show (read x :: Double)\r
+  > strId "1"\r
+  "1.0"\r
+  > strId "1.0"\r
+  "1.0"\r
+  ~~~\r
+  The type annotation is needed here, because `read` parses a string\r
+  to a certain type of values, `show` converts it back to string,\r
+  and the behavior of the composition depends on what the intermediate type is.\r
+  There is however not enough information for the compiler to infer the type\r
+  (it is shown as `?a` in the error message). \r
+* Code specialized to a certain type may be more efficient than a generic code\r
+  that applies to all data types.\r
+A type of an expression or identifier is annotated by adding `::` and a type\r
+expression after it. Type annotations may also be used in patterns:\r
+~~~\r
+sign (x :: Double) = compare x 0 \r
+~~~\r
+\r
+\r
+----\r
+The following types (or more exactly, type constructors) are built in the SCL compiler:\r
+* `Boolean`\r
+* `Byte`, `Short`, `Integer`, `Long`\r
+* `Float`, `Double`\r
+* `String`\r
+* `[]`\r
+* `()`, `(,)`, `(,,)`, ...\r
+* `(->)`\r
+* `Maybe`\r
+* `Array`\r
+* `BooleanArray`, `ByteArray`, `ShortArray`, \r
+  `IntegerArray`, `LongArray`, `FloatArray`, `DoubleArray`\r
+\r
+Other type constructors are defined in SCL modules, either importing them from Java\r
+or using `data` declaration.\r
+Except for the couple of special cases in the previous list, the names of \r
+all type constructors are capitalized.\r
+\r
+Some type constructors are parametric (compare to generics in Java or templates in C++).\r
+For example, the list type constructor `[]` has one parameter: the type of the list\r
+elements. Thus `[Integer]` is the type of the integer lists and `[String]` \r
+is the type of string lists. \r
+`[[Integer]]` is the type of the lists of integer\r
+lists. Parameters are usually written after the parametric type constructor: \r
+for example `Maybe Integer` or `Array String`, but some of the builtin type \r
+constructors can be written in a special way in order to make the type \r
+expressions more readable:\r
+~~~\r
+[a] = [] a\r
+(a,b) = (,) a b\r
+(a,b,c) = (,,) a b c\r
+...\r
+a -> b = (->) a b\r
+~~~\r
+\r
+Particularly important type constructor is `(->)` for building function types.\r
+For example, the type of the function computing the length of a string is `String -> Integer`: \r
+the function takes a string as a parameter and returns an integer.\r
+\r
+Types of the functions taking multiple parameters are written by composing function types. \r
+For example, the type of a function taking nth element of a string list is \r
+`[String] -> Integer -> String`. The function takes a string list and an integer as\r
+a parameter and returns a string. Function type operator `->` is right associative\r
+thus the previous type is equivalent to `[String] -> (Integer -> String)`. \r
+Thus the type expression can be read as well as a type of functions taking a string\r
+list and returning another function from integers and strings.\r
+\r
+`(a,b)` is the type of pairs where the first component of the pair has type `a`\r
+and the second component has type `b`. Tuple types `(a,b,c)`, `(a,b,c,d)` etc. \r
+are defined similarly. `Maybe a` is the type of optional values.\r
+\r
+\r
+----\r
+Many functions can be defined so that they do not need to know the exact types they are operating with.\r
+Such unknown types can be filled in type expressions by type variables: for example the function\r
+we discussed earlier that took nth element of a string list does not need the information that\r
+list elements are strings in its implementation and so it can be given a more generic type\r
+`[a] -> Integer -> a`, i.e a function taking a list of `a`:s and an integer as a parameter\r
+and returning a single `a`.\r
+\r
+Type variables may also refer to parametric types, but all useful examples involve type constraints we describe below.\r
+\r
+\r
+----\r
+### Exercise*\r
+\r
+Function types with type variables tell quite much about the function assuming it is total,\r
+i.e does not hang or throw a runtime exception with any parameters. Write the *unique*\r
+functions with the following type signatures:\r
+~~~\r
+a -> a\r
+(a,b) -> (b,a)\r
+~~~\r
+Write all possible functions with the following type signatures:\r
+~~~\r
+a -> a -> a\r
+~~~\r
+\r
+Because SCL Console does not support definition of functions with generic types,\r
+this exercise can be done only by writing your own SCL module.\r
+\r
+----\r
+SCL does not support function overloading at least in the way Java and C++ support it.\r
+This means that every function has a unique type signature. Now consider the addition function\r
+`(+)`. We could defined its signature for example as `Integer -> Integer -> Integer`,\r
+but then we would need some other name for the sum of doubles `Double -> Double -> Double` or\r
+strings `String -> String -> String`. It would seem like the right signature would be\r
+`a -> a -> a`, but that is not satisfactory either, because then the function had to\r
+somehow support all possible types. \r
+\r
+The solution to the problem is to constraint the set of allowed types for the type variable.\r
+Such a constrained type is written in the case of addition function as\r
+`Additive a => a -> a -> a`. The constraint `Additive a` is composed of a type class\r
+`Additive` followed by parameters of the constraint. \r
+The type can be understood in two different ways. A logical reading is\r
+> For any additive type `a`, the function takes two `a`:s as parameters and returns `a`.\r
+and an operational reading that gives a good intuition what is happening in runtime\r
+>  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
+\r
+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
+~~~\r
+getNth :: Sequence s => s a -> Integer -> a\r
+~~~\r
+\r
+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
+~~~\r
+(+) :: Additive a => a -> a -> a\r
+(*) :: Ring a => a -> a -> a\r
+~~~\r
+and Additive is a superclass of Ring a. A function using both operators need to specify only Ring as a constraint:\r
+~~~\r
+doubleAndAddOne :: Ring a => a -> a\r
+doubleAndAddOne x = 2*x + 1\r
+~~~\r
+\r
+This is a hierarchy of ``numerical'' type classes defined in the standard library of SCL:\r
+\r
+\includegraphics[scale=0.6]{figures/TypeClasses.png}\r
+\r
+The white boxes are type classes. An open arrow between type classes is the inheritance between type classes.\r
+The yellow boxes are types defined in the standard library. They are connected to the type classes\r
+they belong to.\r
+\r
+There are also type classes for converting values to strings `Show` and vice versa `Read`.\r
+Types in the type class `Hashable` provide a method to compute a hash code.\r
+Types in the type class `Serializable` can be serialized to a byte array and deserialized back to a value.\r
+There are also some type classes that make programming with different containers more generic:\r
+`Functor`, `Monad`, etc. \r
+\r
+\r
+----\r
+SCL functions are referentially transparent which means that they are like\r
+mathematical functions always returning the same value for the same parameters\r
+and not causing any observable side-effects. This seems extremely restrictive\r
+because most of the programs are written in order to generate some kind of\r
+side-effects and even completely mathematical algorithms involve functions\r
+that are not referentially transparent such as generation of random numbers.\r
+\r
+This policy does not however restrict expressive power of the language because\r
+functions can return and manipulate *descriptions of computations*.\r
+These computations are then executed by some external means.\r
+Two different ways of handling computations in SCL are monads and effect types.\r
+Effect types are not applicable to as large range of different\r
+computation concepts as monads are but they are easier to work with.\r
+\r
+An effectful computation has type `<effects> t`.\r
+The type after angle brackets is the type of the value obtained by the computation.\r
+Side-effects that might happen during the computation are listed inside of angle brackets.\r
+Effect types must always occur as a return type of a function. Here are some examples (some fictional) \r
+of functions with side-effects:\r
+~~~\r
+randomBetween :: Double -> Double -> <Nondet> Double\r
+resource :: String -> <ReadGraph> Resource\r
+claim :: Resource -> Resource -> Resource -> <WriteGraph> ()\r
+randomLiteral :: Double -> Double -> <Nondet,WriteGraph> Resource\r
+~~~\r
+\r
+Effect types are much like type constraints: you can mostly ignore them when using functions.\r
+All effects you use are automatically collected and added to the type signature of the defined\r
+function (or checked against type annotation if provided).\r
+\r
+Like type classes, effects form a hierarchy. For example WriteGraph inherits ReadGraph\r
+and a function both reading and writing to graph is annotated only with `<WriteGraph>` effect.\r
+\r
+Like types, effects can also be abstracted with effect variables. This is important when defining generic\r
+functions that manipulate possibly effectful functions:\r
+~~~\r
+executeTwice :: (() -> <e> ()) -> <e> ()\r
+executeTwice f = do f () ; f ()\r
+\r
+(.) :: (b -> <e2> c) -> (a -> <e1> b) -> (a -> <e1,e2> c)\r
+(f . g) x = f (g x)\r
+~~~\r
+\r
+\r
+----\r
+### Exercise\r
+Revisit the earlier lessons listing library functions and their types. \r
+Can you now understand all the type signatures?\r
+\r
+\r
+## Side-effects\r
+\r
+----\r
+So far our examples have used pure functions without side effects.\r
+There are indeed quite few functions in the standard library producing\r
+side effects. One of them is the printing function: \r
+~~~\r
+> print "Hello world!"\r
+Hello world!\r
+~~~\r
+\r
+Side-effectful function applications can be sequenced \r
+in a `do` block:\r
+~~~\r
+> do print "Hello,"\r
+     print "    World!"\r
+Hello,\r
+    World!     \r
+~~~\r
+\r
+----\r
+It is very typical that we want to cause some effect for\r
+every element of some list. For that purpose there is a function `for`:\r
+~~~\r
+> for [1..3] print\r
+1\r
+2\r
+3\r
+~~~\r
+\r
+Here is a little more complicated example:\r
+~~~\r
+> items = ["patridge in a pear tree", "turtle doves",\r
+           "french hens", "colly birds", "gold rings",\r
+           "geese-a-laying", "swans-a-swimming", "maids-a-milking",\r
+           "ladies dancing", "lords-a-leaping", "pipers piping",\r
+           "drummers drumming"]\r
+> numbers = ["and a", "two", "three", "four", "five", "six",\r
+             "seven", "eight", "nine", "ten", "eleven", "twelve"]\r
+> printVerse n = do\r
+      print "On the twelfth day of Christmas, my true love gave to me"\r
+      for [1..n] (\i -> do\r
+          c = n-i\r
+          print $ (if n==1 then "a" else numbers!c) + " " + items!c\r
+      )\r
+      print ""\r
+> for [1..12] printVerse\r
+...\r
+~~~\r
+\r
+\r
+----\r
+### Exercise\r
+Procude the lyrics of the song ``99 Bottles of Beer''\r
+<http://www.99-bottles-of-beer.net/lyrics.html>.\r
+\r
+\r
+----\r
+Sometimes it is useful to introduce a state that can be modified\r
+during an algorithm. Such a state is created with function `ref`,\r
+it is accessed with `getReg` and modified with `(:=)` operator:\r
+~~~\r
+> nRef = ref 1\r
+> for [1..8] (\_ -> do \r
+      n = getRef nRef\r
+      print n\r
+      nRef := 2*n\r
+  )\r
+1\r
+2\r
+4\r
+8\r
+16\r
+32\r
+64\r
+128\r
+~~~\r
+\r
+\r
+----\r
+### Exercise\r
+Reproduce the `gcd` function by using modifible state.\r
+\r
+\r
+----\r
+This is a partial list of functions in the standard library producing side-effects:\r
+\setlength\LTleft{-2cm}\r
+<table><tr><td>\r
+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
+print </td><td> Show a => a -> <Proc> () </td><td> prints the given value </td></tr><tr><td>\r
+ref </td><td> a -> <Proc> (Ref a) </td><td> creates a state </td></tr><tr><td>\r
+getRef </td><td> Ref a -> <Proc> a </td><td> accesses a state </td></tr><tr><td>\r
+(:=) </td><td> Ref a -> a -> <Proc> () </td><td> modifies the state </td></tr><tr><td>\r
+newArrayList </td><td> () -> <Proc> ArrayList a </td><td> creates an array list </td></tr><tr><td>\r
+addArrayList </td><td> ArrayList a -> a -> <Proc> () </td><td> add an element at the end of the list </td></tr><tr><td>\r
+getArrayList </td><td> ArrayList a -> Integer -> <Proc> a </td><td> gets an element from the list </td></tr><tr><td>\r
+lengthArrayList </td><td> ArrayList a -> <Proc> Integer </td><td> returns the current lenght of the list </td></tr><tr><td>\r
+freezeArrayList </td><td> ArrayList a -> <Proc> [a] </td><td> freezes the list and returns the corresponding immutable list\r
+</td></tr></table>\r
+\r
+\r
+## Browsing Simantics database\r
+\r
+----\r
+The functionality we have used so far has been readily available in the console.\r
+There is also functionality that must be imported before using:\r
+~~~\r
+> import "Simantics/Ontologies"\r
+~~~\r
+The string `Simantics/Ontologies` is the name of the *SCL module* that is imported.\r
+We assume that the import command is excuted in the rest of this section. \r
+\r
+\r
+----\r
+In order to browse the database more conveniently, let's define some helper functions.\r
+~~~\r
+> nameOfResource r = match possibleRelatedValue r L0.HasName with\r
+    Just name -> name\r
+    Nothing -> "no name"\r
+> printNames (rs :: [Resource]) = \r
+      for rs (\r -> print $ nameOfResource r)    \r
+> findEntities (p :: Resource -> <ReadGraph> Boolean) = findRecursively\r
+    where\r
+      findRecursively r = do \r
+          children = concatMap findRecursively $ immediateChildren r\r
+          if p r\r
+          then [r] + children\r
+          else children\r
+      immediateChildren s = s # L0.ConsistsOf     \r
+> findByType t = findEntities (flip isInstanceOf t)\r
+> aprosOntologies = resource "http://www.apros.fi"\r
+> project = currentProject ()\r
+~~~\r
+\r
+Now we can find all connection types defined in the Apros ontologies:\r
+~~~\r
+> printNames $ findByType STR.ConnectionType aprosOntologies\r
+PipelineStructureConnectionType\r
+...\r
+ElectricalNameReferenceConnectionType\r
+~~~\r
+Find all module types:\r
+~~~\r
+> import "http://www.apros.fi/Apros-6.1" as APROS\r
+> printNames $ findByType APROS.AprosModuleType aprosOntologies\r
+~~~\r
+Show all pipes in the workspace with their lengths:\r
+~~~\r
+> import "http://www.apros.fi/Combustion/Configuration-6.0/ModuleTypes" \r
+         as MT\r
+> import "http://www.apros.fi/Combustion/Configuration-6.0/Relations" \r
+         as REL\r
+> for (findByType MT.PIPE project) (\pipe ->\r
+      print $ nameOfResource pipe + " " + \r
+              show (relatedValue pipe REL.PI12_LENGTH :: Float)      \r
+  )\r
+~~~\r
+Find all modules that are not connected anywhere:\r
+~~~\r
+> isUnconnected r = not (existsStatement r STR.IsConnectedTo \r
+                      || existsStatement r APROS.AttachedModule)\r
+> printNames $ filter isUnconnected \r
+             $ findByType APROS.AprosModule project\r
+~~~\r
+\r
+\r
+----\r
+This is a list of most important database accessing functions (the\r
+type `Resource` is abbreviated as `Res` in the type signatures):\r
+\setlength\LTleft{-4cm}\r
+<table><tr><td>\r
+resource </td><td> String -> <ReadGraph> Res </td><td> the resource with the given URI </td></tr><tr><td>\r
+uriOf </td><td> Res -> <ReadGraph> String </td><td> the URI of the given resource </td></tr><tr><td>\r
+(\#) </td><td> Res -> Res -> <ReadGraph> [Res] </td><td> returns all objects for given subject and predicate </td></tr><tr><td>\r
+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
+singleObject </td><td> Res -> Res -> <ReadGraph> Res </td><td> returns the unique object with the given subject and predicate </td></tr><tr><td>\r
+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
+valueOf </td><td> Serializable a => Res -> <ReadGraph> a </td><td> reads a value associated with a resource </td></tr><tr><td>\r
+relatedValue </td><td> Serializable a => Res -> Res -> <ReadGraph> a </td><td> reads a property </td></tr><tr><td>\r
+possibleRelatedValue </td><td> Serializable a => Res -> Res -> <ReadGraph> Maybe a </td><td> reads a possibly existing property </td></tr><tr><td>\r
+inverseOf </td><td> Res -> <ReadGraph> Res </td><td> inverse of a relation </td></tr><tr><td>\r
+singleTypeOf </td><td> Res -> Res -> <ReadGraph> Res </td><td> the unique type of the resource inheriting the given type </td></tr><tr><td>\r
+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
+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
+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
+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
+claim </td><td> Res -> Res -> Res -> <WriteGraph> () </td><td> adds a statement </td></tr><tr><td>\r
+deny </td><td> Res -> Res -> Res -> <WriteGraph> () </td><td> removes a statement </td></tr><tr><td>\r
+claimRelatedValue </td><td> Serializable a => Res -> Res -> a -> <WriteGraph> () </td><td> sets the value of a property </td></tr><tr><td>\r
+syncRead </td><td> (() -> <Proc,ReadGraph> a) -> <Proc> a </td><td> makes a read request </td></tr><tr><td>\r
+syncWrite </td><td> (() -> <Proc,ReadGraph,WriteGraph> a) -> <Proc> a </td><td> makes a write request\r
+</td></tr></table>\r
+\r
+\r
+## Manipulating diagrams\r
+\r
+----\r
+Diagrams could be in principle manipulated with the set of primitive\r
+graph functions introduced in the previous section. There is however\r
+some tools available to work with diagrams at a higher level. \r
+Therefore we need for this section the following imports:\r
+~~~\r
+> import "Simantics/Diagram"\r
+> import "http://www.apros.fi/Apros-6.1" as APROS\r
+> import "http://www.apros.fi/Combustion/Configuration-6.0/Relations" \r
+         as REL\r
+> import "http://www.apros.fi/Combustion/Diagram-6.0/Symbols" \r
+         as SYMBOLS          \r
+> import "http://www.apros.fi/Combustion/Diagram-6.0/Relations" \r
+         as CPS\r
+~~~\r
+\r
+For this section you should also create a model with (default) name Model\r
+and a new diagram to that model with (default) name NewGenericDiagram. If\r
+you want to change these names, you should also change the code\r
+examples accordingly. Populate the diagram with couple of elements and\r
+connect them together.\r
+\r
+\r
+----\r
+We show first how to read the diagram contents:\r
+~~~\r
+> dia = diagram (model "Model") ["NewGenericDiagram"]\r
+> for (elementsOfR dia) print\r
+(Connection [Terminal "SP_01" #221240, Terminal "MU_01" #218187] [Edge 0 1] (Just "XA_02"), #450761)\r
+(Component #217233 "SP_01" (Position ...) [Property #137577, ...], #450756)\r
+(Component #217663 "MU_01" (Position ...) [Property #144599, ...], #450751)\r
+~~~\r
+The actual result depends on how you have populated your diagram.\r
+\r
+The result is not very readable because of all the resource identifiers. \r
+Let's write a pretty-printing function:\r
+~~~\r
+> printElement ((Component t n pos props),_) = do\r
+    print $ n + " :: " + nameOfResource t\r
+    print $ "    " + show pos\r
+    for props (\(Property relation value) ->\r
+        print $ "    " + nameOfResource relation + " " + show value\r
+    )\r
+ printElement ((Connection nodes _ name),_) = do\r
+    print $ "Connection " + \r
+            (match name with Just n -> n ; Nothing -> "")\r
+    printNode (Terminal element connectionPoint) = \r
+        print $ "    " + element + " " + nameOfResource connectionPoint\r
+    printNode otherwise = ()\r
+    for nodes printNode\r
+ printElement ((Flag t name _ _ _ _ _ pos _),_) = do\r
+    print $ "Flag " + name + " :: " + nameOfResource t\r
+    print $ "    " + show pos\r
+ printElement (el,_) = print el // Use the default printing as a fallback \r
+~~~\r
+Now we get:\r
+~~~>  \r
+> for (elementsOfR dia) printElement\r
+Connection XA_02\r
+    SP_01 SP_OUTPUT_SIGN_1_1\r
+    MU_01 MULTIPLYER_INPUT_SIGN_1_1\r
+SP_01 :: SetpointS\r
+    Position 1.0 0.0 0.0 1.0 94.0 115.0\r
+    SP_VALUE 0.0\r
+    SP_MINMAX_ON false\r
+    SP_GRADIENT_UP 60.0\r
+    SP_TRACKING_ON false\r
+    SP_MIN 0.0\r
+    SP_GRADIENT_DOWN -60.0\r
+    SP_FAST_MODE_ON true\r
+    SP_MAX 100.0\r
+MU_01 :: Gain\r
+    Position 1.0 0.0 0.0 1.0 104.0 115.0\r
+    MULTIPLYER_BIAS 0.0\r
+    MULTIPLYER_GAIN 1.0\r
+    MULTIPLYER_OUTPUT 0.0\r
+~~~\r
+\r
+\r
+----\r
+Next, let's create some new diagrams. We need two helper functions:\r
+~~~\r
+> aprosDiagram modelName diagramName = NewDiagram \r
+      (model modelName) \r
+      [diagramName]\r
+      APROS.Folder\r
+      APROS.GenericAprosComposite\r
+> joinMap = createJoinMap ()\r
+~~~\r
+The first function creates a specification for a new diagram:\r
+it describes the model where the diagram is created, the path\r
+to the diagram, the type of folders in the path and finally\r
+the type of the diagram itself. The second definition defines\r
+a `joinMap` that is used for connecting diagrams together (by flags).\r
+\r
+Now we can write:\r
+~~~\r
+> newDia = fst $ createDiagramR (aprosDiagram "Model" "TestDiagram1") joinMap []\r
+~~~\r
+This should create a new diagram with name TestDiagram1. The\r
+last parameter is the list of diagram elements. Because the list\r
+is empty, our diagram is also empty.\r
+\r
+Easiest way to create some content is to copy it from another diagram:\r
+~~~\r
+> sortEls l = filter (not . isReferring) l + filter isReferring l\r
+    where\r
+      isReferring (Connection _ _ _) = True\r
+      isReferring (SimpleConnection _ _ _ _ _) = True\r
+      isReferring (Monitor _ _ _ _) = True\r
+      isReferring otherwise = False\r
+> els = sortEls $ map fst $ elementsOfR dia\r
+> createDiagramR (ExistingDiagram newDia) joinMap els \r
+~~~\r
+This replaces the contents of TestDiagram1 by the contents of NewGenericDiagram.\r
+The function `sortEls` is needed to work around a bug in `createDiagramR`\r
+occurring if some element is created after another element that refers to it.\r
+\r
+\r
+----\r
+Usually we want to modify the contents of the diagram somehow before copying it.\r
+Here are couple of example functions for transforming the elements:\r
+~~~\r
+> mapElementName f (Component t name pos props) =\r
+      Component t (f name) pos props\r
+  mapElementName f (Connection nodes edges possibleName) =\r
+      Connection (map prefixNode nodes) edges (map f possibleName)\r
+    where\r
+      prefixNode (Terminal name cp) = Terminal (f name) cp\r
+      prefixNode n = n\r
+  mapElementName f (Flag t name label output external \r
+                         ioBinding ioTableRowIndex pos refs) = \r
+      Flag t (f name) label output external \r
+           ioBinding ioTableRowIndex pos refs\r
+  mapElementName f el = el // This is not yet a complete definition!\r
+> moveElement delta (Component t name pos props) =\r
+      Component t name (move delta pos) props\r
+  moveElement delta (Connection nodes edges name) =\r
+      Connection (map moveNode nodes) edges name\r
+    where\r
+      moveNode (RouteLine False pos) = RouteLine False (pos + fst delta)\r
+      moveNode (RouteLine True pos) = RouteLine True (pos + snd delta)\r
+      moveNode n = n\r
+  moveElement delta (Flag t name label output external\r
+                          ioBinding ioTableRowIndex pos refs) = \r
+      Flag t name label output external \r
+           ioBinding ioTableRowIndex (move delta pos) refs\r
+  moveElement delta el = el // This is not yet a complete definition!\r
+~~~\r
+Now we can move the elements and add a prefix to them:  \r
+~~~  \r
+> modifiedEls = map (moveElement (20,20)) \r
+              $ map (mapElementName ((+) "PREFIX_")) els\r
+> createDiagramR (ExistingDiagram newDia) joinMap modifiedEls\r
+~~~\r
+\r
+Finally, let's try making some clones of the elements:\r
+~~~  \r
+> modifiedEls = [ moveElement (dx,dy) $ mapElementName ((+) prefix) el\r
+                | i <- [0..3]\r
+                , j <- [0..3]\r
+                , dx = 30 * fromInteger i\r
+                , dy = 30 * fromInteger j\r
+                , prefix = "P_" + show i + "_" + show j + "_"\r
+                , el <- els] \r
+> createDiagramR (ExistingDiagram newDia) joinMap modifiedEls\r
+~~~\r
+\r
+\r
+----\r
+### Exercise\r
+Write a function `createPipeline` that takes as a parameter\r
+a diagram specification and a list of two-dimensional points\r
+and creates a pipeline such that elevations of the points are\r
+the second components of the points in the list, the lengths \r
+of the points are the distances between successive points and\r
+the diagram positions are based on the physical positions.\r
+The following command should work: \r
+~~~\r
+> dia = ExistingDiagram (diagram (model "Model") ["TestDiagram1"])\r
+> createPipeline dia [(1,1), (6,1), (10,5)]\r
+~~~\r
+\r
+Hint: The following commands create a pipe and a point that are connected\r
+together with point elevation and pipe lenght specified:   \r
+~~~\r
+> els = [\r
+      Component SYMBOLS.Point "PO_01" (location 30 30) \r
+                [Property REL.PO11_ELEV (toDynamic 10.0)],\r
+      Component SYMBOLS.Pipe "PI_01" (location 40 30) \r
+                [Property REL.PI12_LENGTH (toDynamic 5.0)],\r
+      Connection [Terminal "PO_01" CPS.PointSelf,\r
+                  Terminal "PI_01" CPS.PI12_CONNECT_POINT_1_1_1]\r
+                  [Edge 0 1] Nothing\r
+  ]\r
+> createDiagramR dia joinMap els\r
+~~~\r
+\r
+\r
+----\r
+### Remark\r
+This is the data type definition of the diagram elements:\r
+~~~\r
+data DiagramElement res = \r
+    Component\r
+        res            // component type\r
+        String         // name\r
+        Position       // position\r
+        [Property res] // properties\r
+  | SimpleConnection String res String res (Maybe String)\r
+  | Connection [ConnectionNode res] [Edge] (Maybe String)\r
+  | Flag \r
+        res \r
+        String         // name \r
+        String         // label\r
+        Boolean        // output\r
+        Boolean        // external\r
+        (Maybe String)  // IOTableBinding\r
+        (Maybe Integer) // IOTableRowIndex\r
+        Position       // position  \r
+        [Dynamic]      // references to the joins\r
+  | SVG String Position\r
+  | Monitor String (Maybe MonitorReference) MonitorVisuals Position\r
+data Position = Position Double Double Double Double Double Double\r
+data Property res = Property res Dynamic\r
+data Edge = Edge Integer Integer\r
+data ConnectionNode res = Terminal String res\r
+                        | RouteLine\r
+                              Boolean   // is horizontal\r
+                              Double    // position\r
+data Font = Font String Integer Integer\r
+data Alignment = Baseline | Center\r
+               | Leading | Trailing\r
+data MonitorReference = MonitorReference String String\r
+data MonitorVisuals = MonitorVisuals (Maybe Font) Double Alignment Alignment                              \r
+~~~\r
+\r
+## Model queries\r
+\r
+----\r
+In this section, we make queries and mass modifications to the components\r
+of a model. For preliminaries, you need to run the import command:\r
+~~~\r
+import "Apros/ModelQueries"\r
+~~~\r
+\r
+It defines the following functions:\r
+~~~\r
+forAllComponentsIn :: (Resource -> <e> a) -> Resource -> <ReadGraph,e> ()\r
+forAllComponents ::  (Resource -> <e> a) -> <Proc,ReadGraph,e> ()\r
+forComponentsIn :: (Resource -> <e> Boolean) -> Resource \r
+                -> (Resource -> <e> a) -> <ReadGraph,e> ()\r
+forComponents :: (Resource -> <e> Boolean) -> (Resource -> <e> a) -> <Proc,ReadGraph,e> ()\r
+searchComponents :: (Resource -> <e> Boolean) -> <Proc,ReadGraph,e> [Resource]\r
+searchComponentsIn :: (Resource -> <e> Boolean) -> Resource -> <ReadGraph,e> [Resource]\r
+\r
+nameSatisfies :: (String -> <e> Boolean) -> Resource -> <e,ReadGraph> Boolean\r
+nameIs name = nameSatisfies (== name)\r
+getName :: Resource -> <ReadGraph> String\r
+\r
+typeIs :: Resource -> Resource -> <ReadGraph> Boolean\r
+\r
+configurationValueSatisfies :: Serializable a => Resource -> (a -> <e> Boolean) \r
+                            -> Resource -> <e,ReadGraph> Boolean\r
+configurationValueIs :: Serializable a => Resource -> a \r
+                     -> Resource -> <e,ReadGraph> Boolean\r
+setConfigurationValue :: Serializable a => Resource -> a -> Resource -> <WriteGraph> ()\r
+getConfigurationValue :: Serializable a => Resource -> Resource -> <ReadGraph> a\r
+\r
+stateValueSatisfies :: Serializable a => Resource -> (a -> <e> Boolean) \r
+                    -> <ReadGraph> (Resource -> <e,ReadGraph> Boolean)\r
+stateValueIs :: Serializable a => Resource -> a \r
+             -> <ReadGraph> (Resource -> <e,ReadGraph> Boolean)\r
+setStateValue :: Serializable a => Resource -> a\r
+              -> <ReadGraph> (Resource -> <WriteGraph> ())\r
+getStateValue :: Serializable a => Resource -> <ReadGraph> (Resource -> <ReadGraph> a)\r
+\r
+(&&&) :: Combinable a => a -> a -> a\r
+instance Combinable (Resource -> <e> Boolean)\r
+instance Combinable (Resource -> <e> ())\r
+\r
+printName :: Resource -> <ReadGraph,Proc> ()\r
+row :: [Resource -> <e> String] -> (Resource -> <e> String)\r
+~~~\r
+\r
+\r
+----\r
+The functions make it possible to define queries to the active\r
+model of the form:\r
+``for all components satisfying a condition execute an action.''\r
+For example:\r
+\r
+1) Print the names of all points in the model:\r
+    ~~~\r
+   forComponents\r
+       (typeIs MODULETYPES.POINT)\r
+       printName\r
+   ~~~ \r
+2) Set area of pipe PIP01 to 0.0033\r
+   ~~~\r
+   forComponents\r
+       (nameIs "PIP01")\r
+       (setConfigurationValue ATTRIBUTES.PI12_AREA 0.2)\r
+   ~~~\r
+3) Find all pipes in the active model and set their area to 0.001 m2:\r
+   ~~~\r
+   forComponents\r
+       (typeIs MODULETYPES.PIPE)\r
+       (setConfigurationValue ATTRIBUTES.PI12_AREA (0.001 :: Float))\r
+   ~~~\r
+4) Find all pipes with area < 0.0001 m2 in the active model and set their area to 0.001 m2:\r
+   ~~~\r
+   forComponents\r
+       (configurationValueSatisfies ATTRIBUTES.PI12_AREA (\(x :: Float) -> x < 0.0001))\r
+       (setConfigurationValue ATTRIBUTES.PI12_AREA (0.001 :: Float))\r
+   ~~~\r
+5) Find all pipes with fluid section WSB and list their boron concentrations:\r
+   ~~~\r
+   forComponents\r
+       (configurationValueIs ATTRIBUTES.PO11_SECTION_NAME "WSB")\r
+       (print . row [getName, showFloat . getStateValue ATTRIBUTES.PO11_BOR_CONC])\r
+   ~~~\r
+6) Find all pipes with fluid section WS and set their fluid section to WSB:\r
+   ~~~\r
+   forComponents\r
+       (configurationValueIs ATTRIBUTES.PO11_SECTION_NAME "WS")\r
+       (setConfigurationValue ATTRIBUTES.PO11_SECTION_NAME "WSB")\r
+   ~~~\r
+7) Find all pipes in diagram Diagram2 and set their length to 123.45 m:\r
+   ~~~\r
+   forComponentsIn\r
+         (typeIs MODULETYPES.PIPE)\r
+         (resource "http://Projects/Development%20Project/Model/Configuration/Diagram2")\r
+         (setConfigurationValue ATTRIBUTES.PI12_LENGTH (123.45 :: Float))\r
+   ~~~  \r
+\r
+----\r
+It is also possible to write the results of a query to a file.\r
+~~~\r
+printingToFile "c:/temp/componentListing.txt" (\r
+    forComponents\r
+        (configurationValueIs ATTRIBUTES.PO11_SECTION_NAME "WSB")\r
+        (print . row [getName, showFloat . getStateValue ATTRIBUTES.PO11_BOR_CONC])\r
+    )\r
+~~~\r
+\r
+\r
+# Further topics\r
+\r
+----\r
+\r
+If you start to use SCL more frequently and write your own helper functions,\r
+it becomes quickly cumbersome to paste them every time into the console.\r
+You can write a list of commands into a separate file and run it with the command\r
+~~~\r
+> runFromFile "c:/file/path"\r
+~~~\r
+Commands are separated from each other by indentation.\r
+\r
+Another way to store function definitions is to write your own modules.\r
+It also frees you from some restrinctions of SCL Console.\r
+You can write the module into a file, say `c:/scl/MyModule.scl`\r
+and import it as:\r
+~~~\r
+> import "file:c:/scl/MyModule"\r
+~~~\r
+What makes working with modules harder than console commands is that\r
+it is not so easy to update a module that you have already imported.\r
+It is however possible by running:\r
+~~~\r
+> reset ""\r
+~~~\r
+that clears the whole SCL environment. After clearing the environment, you \r
+have to reimport all the modules you want to use.\r
+We will improve the situation in next versions of \r
+the SCL environment.\r
+\r
+\r
+----\r
+There are many language features we have not touched in this tutorial.\r
+Many of them are also in Haskell, so you can familize yourself with them\r
+by reading Haskell tutorials:\r
+* defining new data types,\r
+* defining new type classes and their instances,\r
+* defining binary operators, their associativity and precedence.\r
+SCL supports also monads like Haskell. Only difference is that monadic\r
+syntax uses keyword `mdo` instead of `do`. Althought\r
+the importance of monads is lessen in SCL because of effect types,\r
+they are still a useful concept to know. Monads are particularly\r
+useful for building domain specific languages in SCL.\r
+\r
+\r
+----\r
+There are also couple of features that we have not described that\r
+are specific to SCL:\r
+* definition of new effect types\r
+* syntax for importing Java code to SCL, for example:\r
+  ~~~\r
+  importJava "java.util.List" where\r
+      @JavaName get\r
+      (!) :: [a] -> Integer -> a\r
+  \r
+      @JavaName size\r
+      length :: [a] -> Integer\r
+  \r
+      subList :: [a] -> Integer -> Integer -> [a]\r
+  ~~~\r
+* value annotations\r
+  ~~~\r
+  @inline\r
+  curry :: ((a, b) -> <e> c) -> a -> b -> <e> c\r
+  curry f x y =  f (x, y)\r
+  \r
+  @macro\r
+  a && b = if a then b else False\r
+  ~~~\r
+\r
+\r
index 4bfeebffadc11bad23a571dfa5f576fcbb3b6ec9..861f705d7a31dc8061d1848b347cb613ddcdb4ea 100644 (file)
@@ -48,6 +48,7 @@ SEL.TypedVariableTabContribution <T SEL.VariableTabContribution
 SEL.HasDisplayColumn <R L0.HasProperty : L0.FunctionalRelation
 
 SEL.HasFormatter <R L0.HasProperty : L0X.ResourcePropertyRelation
+SEL.formatter ==> "Dynamic -> String" <R L0.HasProperty
 
 SEL.HasDisplayProperty <R L0.HasProperty : L0.FunctionalRelation
   L0.RequiresValueType "String"
index 2eaba75d60db700d72c2d1a337363df7c265ef43..7d90d33926c9d94675dbed2665d44515548f4f15 100644 (file)
@@ -31,6 +31,7 @@ import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
 import org.simantics.layer0.Layer0;
 import org.simantics.modeling.ModelingResources;
+import org.simantics.scl.runtime.function.Function1;
 
 public class DisplayValueVariableAdapter extends SimpleContextualAdapter<Variable, ModelledVariablePropertyDescriptor> {
        
@@ -117,20 +118,28 @@ public class DisplayValueVariableAdapter extends SimpleContextualAdapter<Variabl
        String expression = possibleExpression(graph, property);
        if(expression != null) return expression;
        
-       Object value = property.getValue(graph);
+       Object value = null;
 
        Resource formatter = property.getPossiblePropertyValue(graph, Variables.FORMATTER);
        if(formatter != null) {
                Formatter fmt = graph.adaptContextual(formatter, property, Variable.class, Formatter.class);
-               value = fmt.format(value);
-       } else {
+               value = fmt.format(property.getValue(graph));
+       }
+       if(value == null) {
+               SelectionViewResources SEL = SelectionViewResources.getInstance(graph);
+               Function1<Object,String> formatterFunction = property.getPossiblePropertyValue(graph, SEL.formatter);
+               if(formatterFunction != null) {
+                       value = formatterFunction.apply(property.getValue(graph)); 
+               }
+       }
+       if(value == null) {
 
                Datatype dt = property.getPossibleDatatype(graph);
                if(dt != null) {
                        if(!isPrimitive(dt)) {
                                Binding binding = Bindings.getBinding(dt);
                                try {
-                                       value = DataValuePrinter.writeValueSingleLine(binding, value);
+                                       value = DataValuePrinter.writeValueSingleLine(binding, property.getValue(graph));
                                } catch (IOException e) {
                                        e.printStackTrace();
                                } catch (BindingException e) {
index 7d9d1dba8b02bfcddc51526ff42a6f0491940949..79541b06134deb344a5f6f71c4dda854edcfc145 100644 (file)
@@ -53,7 +53,9 @@ import org.simantics.scl.compiler.types.TVar;
 import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.compiler.types.Types;
 import org.simantics.scl.reflection.annotations.SCLValue;
+import org.simantics.scl.runtime.function.Function1;
 import org.simantics.selectionview.SelectionInput;
+import org.simantics.selectionview.SelectionViewResources;
 import org.simantics.selectionview.StandardSelectionInput;
 import org.simantics.ui.colors.Colors;
 import org.simantics.ui.fonts.Fonts;
@@ -451,15 +453,20 @@ public class All {
                        Object value = null;
                        Resource formatter = property.getPossiblePropertyValue(graph, Variables.FORMATTER);
                        if(formatter != null) {
-                               
                                Formatter fmt = graph.adaptContextual(formatter, property, Variable.class, Formatter.class);
                                value = fmt.format(property.getValue(graph));
-                               
-                       } else {
+                       }
+                       if(value == null) {
+                               SelectionViewResources SEL = SelectionViewResources.getInstance(graph);
+                               Function1<Object,String> formatterFunction = property.getPossiblePropertyValue(graph, SEL.formatter);
+                               if(formatterFunction != null) {
+                                       value = formatterFunction.apply(property.getValue(graph));
+                               }
+                       }
+                       if(value == null) {
 
                                Variant variant = property.getVariantValue(graph);
                                value = variant.getValue();
-                               
                                Binding binding = variant.getBinding();
                                if(binding != null) {
                                        Datatype dt = binding.type();   
index 9e409d9df4bd04a0aef4c19008e9db92484b9508..6469aaff9dd70cfb8a1f29b941eb812a9050010c 100644 (file)
                <module>org.simantics.scl.reflection</module>
                <module>org.simantics.scl.rest</module>
                <module>org.simantics.scl.runtime</module>
+               <module>org.simantics.scl.tutorial</module>
                <module>org.simantics.scl.ui</module>
                <module>org.simantics.selectionview</module>
                <module>org.simantics.selectionview.ontology</module>
index ff6c75f80ad2fbc13928a66ad375fa5a86296c24..30dc6a181c853377bf027ca0dca0e2becea62629 100644 (file)
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.simantics.scl.tutorial"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>