[Web site restructuring. Every document driving the web sit is now in the web/ subdirectory, old directories doc and logos have ben deleted and the example program descriptions have been moved to the new location. nordland@csee.ltu.se**20081111135042] { hunk ./doc/summary/bindings.html 1 - -
--Patterns occur in several syntactic contexts in Timber (e.g. in the left hand sides of bindings, lambda expressions -and case alternatives). Syntactically, patterns form a subset of expressions; a pattern is one of the following: -
-At run-time, patterns are matched against values. Pattern-matching may succeed or fail; in the former case the result -is a binding of the variables in the pattern to values. The rules are as follows: -
-The special "wildcard" variable _ may be used in patterns; in contrast to other variables, it is not bound - by pattern-matching. -
- A consequence of the way pattern-matching is done is that patterns must be linear; no variable may occur more than once in - a pattern. - -
-Syntactically, bindings are divided into type signatures and equations. Equations are either function bindings, pattern bindings - or instance bindings for implicit struct types. - -
- var (, var ) * :: qtype -
Here a qtype is a (possibly qualified) type. -
Examples - | -
---|
x, y, z :: Int |
map :: (a -> b) -> [a] -> [b] |
elem :: a -> [a] -> Bool \\ Eq a |
We present first the simplest form of function definition, a sequence of equations, and then how these may -be extended with where-clauses and with guards; these extensions may be combined. -
-var pat * = expr -
-The variable (the name of the function) and the number of patterns must be the same in all equations. -The order of equations is significant; when applying the function, pattern-matching is tried starting wih the first equation -until it succeeds; the function value is computed from right hand side of that equation, using the variable bindings obtained. -Within one equation, patterns are matched from left to right. -
Example - | -
---|
zip (x:xs) (y:ys) = (x,y) : zip xs ys |
zip _ _ = [] |
-A binding may have attached a where-clause with a list of local bindings in layout-sensitive syntax
-var pat * = expr
- where bind +
-
Example - | -
---|
formatLine n xs = concatMap f xs |
where f x = rJust n (show x) |
-var pat *
- ( | (qual) +
- = expr ) +
-
-In the most common case, a qual is a Boolean expression. After pattern-matching has succeeded, the guards are -evaluated in turn; the right hand side corresponding to the first true guard (if any) is used. -
Example - | -
---|
lookup x [] = Nothing |
lookup x ((a,b) : xs) |
| x == a = Just b |
| True = lookup x xs |
-More complicated guards that bind variables are possible, but omitted here. -
-pat = expr -
-where pat is not a variable (in which case the binding is, perhaps counter-intuitively, a function binding). -
-Pattern bindings bind the variables in pat by pattern-matching against the value of expr. -A pattern binding may not occur as a top-level declaration, but only as a local binding. -
Example - | -
---|
lookup' x ps = y |
where Just y = lookup x ps |
The pattern-binding in the where-clause will fail (and the function application give a run-time error), if -the result of calling lookup is Nothing. -
-implicit var :: type
-funBind
-
-The type signature of an instance of an implicit type is prepended by the keyword implicit. For instances, -a type signature is compulsory; only the function binding defining the instance is not sufficient, -
-The order between bindings in a sequence of bindings is not significant, with the following exceptions: -
-Function bindings are recursive. For pattern bindings certain limited forms of recursion are possible, in order -to build finite, cyclic data structures. To be described more... - rmfile ./doc/summary/bindings.html hunk ./doc/summary/default.html 1 - -
--Default declarations come in two distinct forms. They share the keyword default and they both -affect instances for implicit struct types, but otherwise they serve quite different purposes. -
- For a given implicit struct type T, several instances are typically defined. It is permitted to define - instances at overlapping types, such as e.g. T [a] and T [Int], where the latter type - is more specific than the former. -
- During type-checking, the compiler - needs to insert instances as implicit arguments to functions that use of the selectors of T. The compiler infers - which instance type T t that is needed and chooses the most specific instance. However, it may happen that there - is no most specific type. The prelude defines intInt :: IntLiteral Int and intFloat :: IntLiteral Float and similarly for - Show. Neither of - this is more specific than the other. Thus a top-level definition such as -
s = show 1 -- leads to problems; should - implicit arguments for Int or Float be inserted? There is no reason to prefer one to the other so s is - considered ill-typed. But the matter can be decided by inserting a default declaration; the prelude declares -
-default intInt < intFloat --which means that the instance intInt is to be preferred to intFloat. Thus the Int instances -are chosen and s is "1" rather than "1.0". -
-A declaration -
-default tD :: T D --where T is an implicit struct type and D is a data type produces automatically an instance following -the ideas of Hinze's and Peyton Jones' derivable type classes. The mechanism applies only in some, rather restrictive, situations, -but these include common cases like the Prelude's Eq and Ord, for which it is easy but tedious -to define instances for a new data type. -
-The method applies only to one-parameter implicit -types, for which the types of all selectors are simple, according to the following inductive definition: -
-In addition to the above mechanism, default instances can be defined for implicit types Show and Parse (defined in the Prelude), but as yet only for enumeration types (pending decisions on proper definitions of predefined implicit types for -conversion between values of data types and strings). - - - rmfile ./doc/summary/default.html hunk ./doc/summary/expr.html 1 - -
--Timber has a rich expression language and we divide -the description in three parts: -
Here we describe the Timber form of expression forms that have counterparts in most functional languages. -
These forms are special to Timber and provide the building blocks for - object-oriented programming. -
Every Timber program will include expressions from the previous two groups. In this - third group we describe more esoteric forms that may be ignored by the beginning Timber programmer. -
-Layout of program code is significant in Timber. In many cases, sequences of syntactic elements can be written in -tabular form, where each new item starts on a new line and in the same column as the beginning of the previous item. Multi-line -items are possible by intending subsequent lines; the end of the sequence is signalled by "outdenting", i.e. indenting -less, as in the example -
- showSeq xs = concat (map showLine xss) - where prec = 100 - showLine x = map (showItem 10) - (comp prec xx) - - showItem n x = format n ('_' : g x) --
-The definition of showSeq has a where-clause with a list of two local definitions (defining prec and -showLine). The definition of showLine spans two lines, indicated by indentation. The last definition, -of showItem, has another indentation level, thus is not part of the where-clause and is hence not -local to showSeq. Instead showSeq and showItem form another list of bindings. -
-It is possible to avoid layout-sensitive syntax by enclosing such sequences in braces and using semi-colon as -separator: let {x=1; y=f x 3} in g x y; this is generally not recommended. - -
-
Examples - | -
---|
x, counter, Dictionary.d, (+) |
-
Type of literal - | -Examples - | -
---|---|
Int | 37, 0, -123 |
Float | 1.23, 3E12, 0.4567E-6 |
Char | 'a', '3', '\n', '\t', '\\' |
String | "Hi", "Error\n" |
-Every occurrence of an integer literal except in patterns is during desugaring replaced by application of the function -fromInt to the literal. The Prelude defines -
-implicit struct IntLiteral a where - fromInt :: Int -> a --and instances for Int (the identity function) and Float (conversion). -
-This device will make many functions that mention integer literals usable for both Int and Float arguments; -a simple example is -
-sum :: [a] -> a \\ Num a, IntLiteral a -sum [] = 0 -sum (x : xs) = x + sum xs --
Examples - | Comments | -
---|---|
f 3 | Parentheses not needed |
g (x+2) | Parentheses necessary |
Just (f x) | Constructor Just applied to f x |
map f (g xs) | map f applied to g xs |
hMirror (x,y) | One argument, which is a pair |
-
Examples - | Desugared forms | -
---|---|
x+3 | (+) x 3 |
f x+3*x | (+) (f x) ((*) 3 x) |
3 `elem` xs | elem 3 xs |
-Precedence and associativity of operators is determined syntactically; see the name page for details.
-\ pat + -> expr -
-denoting anonymous functions. The sequence of patterns must be linear, i.e. may not include more than one occurrence -of any variable. -
Example - | -
---|
\x -> x+3 |
\ (Just x) d -> insert x 0 d |
-Pairs, triples etc are expressed using parenheses as delimiters and comma as separator. These are also desugered to -application: -
-
Examples - | Desugared forms | -
---|---|
(a,b) | (,) a b |
(f x,3+5,True) | (,,) (f x) ((+) 3 5) True |
-Here (,), (,,) etc are primitive constructors for the types of pairs, triples etc. -
List expressions are sequences delimited by square brackets and with comma as separators;[1,3,7] -is a list with three elements. This form is desugared to the primitive form of lists, which has as constructors -[] (the empty list) and : ("cons", which builds -a list with its first argument as first element ("head") and second argument as remainder ("tail")). -
-
Examples - | Desugared forms | -
---|---|
[1,3,7] | (:) 1 ((:) 3 ((:) 7 [])) |
[f x, p 3] | (:) (f x) ((:) (p 3) []) |
- -
-let bind + in expr -
where the list of bindings is layout-sensitive. The bindings are recursive, i.e all the -names defined in the bind list are in scope in the right hand sides of these bindings (and, of course, -in the main expression). -
-
Example - | Comments | -
---|---|
let size = f 100 | f, defined below, is in scope |
f 0 = 0 | Pattern-matching allowed |
f x = g x (x+2) | |
in concat (map f xs) |
-
-[ type_constructor ] { field (, field )+ }
where field
- has the form selector = expr .
- The type_constructor is the name of a struct type. Since the struct type is uniquely determined
-by its fields, the type name is optional.
-
Examples - | -
---|
Point {x=3, y=1} |
{x=3, y=1} |
Counter {inc = inc, read = read} |
The examples presupposes type definitions -
-struct Point where - x, y :: Int - -struct Counter where - inc :: Action - read :: Request Int --
-The last example is to emphasise that selectors (the inc and read in the left hand -sides of the fields) are in a separate namespace from variables (the right hand sides). Thus the equations -are not recursive; the example requires -that definitions of these variables are in scope. -
-type_constructor { [ field (, field )+] ..}
-The trailing .. indicates that the struct value should be stuffed, by adding fields -of the form x = x for each selector x that is not explicitly given a value in a field. -
-
Example - | -expands to - | -
---|---|
Counter {..} | Counter {inc = inc, read = read} |
Counter {read = readreq ..} | Counter {read = readreq, inc = inc} |
Point {x=0..} | Point {x=0, y=y} |
-Obviously, because of subtyping, the type name cannot be omitted here. -
-struct bind +
-where the bindings have layout-sensitive syntax. -
-
Example - | -
---|
implicit showList :: Show [a] \\ Show a |
showList = struct |
show [] = "[]" |
show (x : xs) = '[':show x ++ preC (map show xs)++"]" |
-The list of bindings in this form of expression differs from all other occurrences of -lists of bindings in that they are not recursive. We are defining the selectors in a struct -but allow pattern matching equations in layout-sensitive form; occurrence of the same name as a -variable in the right hand side must refer to some other definition in scope. This is particularly -common for structs defined to be type classes, as here. See the section on type classes for -more explanatation. -
-case expr of alt + -
-where the sequence of alternatives is layout-sensitive. The simplest form of an alternative is -
-pat -> expr -
Example - | -
---|
case f a b of |
[] -> 0 |
x : xs -> g x + h 3 xs |
-
-Classes in Timber should be thought of as in object-oriented programming: a class is a template, from which -we may create several objects. An object encapsulates its own copy of the state variables defined in the class. -
Actions and requests are methods that a class may expose to the outside; they may manipulate the local -state of objects. -
-Procedures are subroutines that may be called by actions and requests; they are typically not exposed -in interfaces. In contrast to actions and requests, a procedure always reads and writes the local state -of its caller, irrespective of the scope in which it was defined. -
-The syntax of these constructs are similar; they are all built from sequences of statements: -
-In all cases, statement sequences have layout-sensitive syntax. See the statements page -for further descriptions. -
-To be written. - rmfile ./doc/summary/expr.html hunk ./doc/summary/haskell.html 1 - -
--Much of Timber syntax is taken from Haskell, so the Haskell programmer glancing -through Timber code will feel at home. This page summarizes instead the most important -differences between Timber and Haskell. -
-
-typeclass Eq a where - (==),(/=) :: a -> a -> Bool - - -instance eqUnit :: Eq () -eqUnit = struct - _ == _ = True - _ /= _ = False --
-One cannot attach a deriving-clause to a data type definition. Instead, one can separately -request default instances of some implicit types. -
-elem :: a -> [a] -> Bool \\ Eq a -elem x [] = False -elem x (y : ys) = x == y || elem x ys --
- Note: A call to elem will evaluate both arguments - completely (because the language is strict), but will not traverse its second argument - further when an equality becomes True (because the disjunction "operator" || is non-strict - in its right operand). -
-Further, methods execute concurrently, but with exclusive access to the state of the object; thus Timber is also a concurrent -language with some real-time constructs. -
-This document aims to provide a summary of the language constructs of Timber, including -syntax descriptions but with very little of motivation, explanation and examples. -
-It is intended to be useful for a reader who is exploring Timber and wants a reasonably -concise summary of the language. A Timber tutorial, with extensive motivation and examples, -will be a separate document. -
-Some syntactic constructions are described in simple BNF syntax, but this document does not give -complete formal syntax for Timber. In BNF descriptions, terminals are in -typewriter font, nonterminals in italics and meta symbols in red. - rmfile ./doc/summary/intro.html hunk ./doc/summary/java.html 1 - -
--Timber can be seen as an object-oriented programming language with -many familiar features, but also some less familiar. This page summarizes -both similarities and differences. -
-struct Counter where - incr :: Action - reset :: Action - read :: Request Int --
-A class that implements this interface provides two actions - (asynchronous methods, that do not return results): incr - to increment the local integer state by one, and reset to - reset the state to zero. To query the state, we use the request - (synchronous, value-returning method) read, which simply returns - the value of the state. -
-counter initVal = class - val := initVal - - incr = action - val := val + 1 - - reset = action - val := 0 - - read = request - result val - - result Counter {..} --
- The class itself starts with the keyword class. We see - the initialization of the state variable val to initVal, - the three method declaration and finally the result specification; - here Counter {..} means: assemble a value of type Counter - from definitions in scope. -
- Note that there is no constructor method within the class. Within - the methods of another class we may write -
- c1 = new counter 0 - c2 = new counter 10 -- to create two counter objects, with initial value 0 and 10, respectively. -
-counter :: Int -> Class Counter -- i.e., it is a function that when applied to a integer (the start value) returns a - class, from which we later can create objects. -
-A Timber program may contain two kinds of comments: -
-A Timber program consists mainly of definitions that give meaning to names. There are six -separate namespaces in Timber: -
-Names are simple or qualified; the latter are used to disambiguate names defined in different modules. -
-Simple names come in two lexically distinct forms, identifiers and operators. -
-An identifier consists of a letter followed by zero or more letters, digits, single quotes and underscores. -The initial letter must be upper case for constructors, type constructors and -module names, and must be lower case for variables, selectors and type variables. The following lexically correct -identifiers are keywords of the language and may not be used as names: -
-action after before case class data -do default else elsif forall if -import in instance let module new -of private request result struct then -type typeclass use where while --
An operator is a sequence of one or more symbol characters. -The symbol characters are defined by enumeration: :!#$%&*+\<=>?@\^|-~. -An operator starting with : is a constructor; otherwise it is a variable. Only -variables and constructors have operator forms; the other four namespaces contain only -identifiers. The following lexically correct operators are keywords and may not be used -as names: -
-. .. :: := = \ \\ | <- -> -- --
-An identifier may be used as an operator by enclosing it in backquotes; `elem` is an operator. -Conversely, an operator may be used as an identifier by enclosing it in parentheses; (+) is an identifier. - -
Examples: -
Names - | -Possible namespaces - | -
---|---|
Color, T3, T_3, T_3' | constructors, type constructors, module names |
x, env, myTable, a', x_1 | variables, selectors, type variables |
+, #=#, @@ | variables |
:, :++: | constructors |
#3 | ILLEGAL; mixture of operator and identifier symbols. |
-The precedence and associativity of operators are determined by their syntax. The operators in the following table -are listed in decreasing precedence, i.e. an operator that appears in a later row binds less tightly. Function application, -denoted by juxtaposition, binds tighter than all operators. - -
Operators - | -Associativity - | -
---|---|
@ | Right |
^ | Right |
* / `div` `mod` | Left |
+ - | Left |
: ++ | Right |
== /= < > <= >= | None |
&& | Right |
|| | Right |
>> >>= | Left |
$ | Right |
-The operators in the table above are defined in the Prelude, but can be redefined in user modules, except for the following -three exceptions: -
- In harmony with this, the empty list has the (lexically illegal) name []. -
- This means that, if evaluation of a in -a && b gives False as result, the result of the complete expression is False and -b is -not evaluated (and, in particular, a runtime error or non-termination that would occur during evaluation of b is avoided). -
-Similarly, if the left operand to || evaluates to True, the result of the complete expression is -True without evaluating the right operand. -
-Thus, semantically speaking, && and || are not operators at all but special expression-forming constructs.
-Timber modules are used to manage namespaces. In this mechanism, simple names are extended to qualified forms, where the -simple name is prefixed by the name of the module where it is defined. To allow several modules with the same name in a system, -module names themselves may be qualified. -
A qualified module name is a sequence of simple module names interspersed with periods, such as -Data.Functional.List. The module name (given in the module header) is here just List, but the full name must be used by -importing clients and is also used by the Timber installation to store and retrieve modules in the file system. Exactly how this is done is -installation-dependent. -
-Imagine a module Dictionary, which defines among others the names insert and |->. An importing module may -refer to these names using the qualified forms Dictionary.insert and Dictionary.|-> in order to avoid possible name conflicts. See the modules page for more information on import and use of other modules.The simple name that is the suffix of a qualified name decides if the -name is an operator or an identifier and if it is a constructor or not. -
-A qualified name may not be used at a defining occurrence, only when a name is used. (The module prefix is uniquely determined by -the module name, hence superfluous in the definition.) - rmfile ./doc/summary/lex.html binary ./doc/summary/logo.gif oldhex *4749463839615a019c00f700003636363838383e3e414343434c4c4c4d4f5b52535b5353535758 *5b5b5b5b616161686c866b6b6b6e59366f7286735c39735e4073624a7460457474747566557760 *3f78726a797b877a664b7a76707b623d7b63427b6c667b6d597c7c7c7d694b7d6a507f79747f80 *87806640806c508075798080808084a182838a8374698389b484725584735c848693856a42857e *8e85889c867d81868aa2877d7c878889888293898ca3898dab8a6e448a87a38a8a8a8a8fb18b8c *928b8d9b8b90ab8b91b38c7c668d71468d80768d92bb8e90a38f72488f95c48f96c8908e8a9091 *b89198cc92826c92867a928b93928ea79292929294a3929ad49375499385759393999397b3949d *db959fe196784b9698a3969abb96a0e597897697a1ea989cc398a3ec997a4c9990939aa3e29aa5 *f39b8d7a9b9ca29b9cac9ba1d09ba3dc9ba6f99d9d9d9e9eb29e9ebd9ea2c29ea8ee9eaafe9f7f *509f804f9fa0a39fa2bc9fa8e2a07f4fa07f50a09aa5a19484a1a9e8a1abf2a1adfea29b93a2a2 *a3a38251a3a4b3a3a7d5a3abe1a4a8c5a4aadba5b1fea69b8ca6a4aba6b0f5a7a8afa7a8b3a886 *53a9acd5aab1e1aab5feababababadc9abb1daabb2ecabb4f2ac8955acacb4acacbcada498aeb0 *d6aeb8feaf8c58b08c57b0b5dbb28e58b2acacb2b2b2b2bcfeb3b4bab3b4c7b3b5d6b3b8e4b4aa *9eb4bbf2b6915ab6c0ffb7bbdbb9945cb9bcccbab2a6bab3acbabde3bbbbbbbbbcd5bbc3febcc2 *eebcc2f3be985ebeb8b1bec2ddbfbdc0c0c7fec1bcc1c2c2d6c2c6e6c2c8f3c39c61c3c5dbc3ca *fec4bdb5c6c6c6c6c6c9c89f63c8c6d4c8cefec9cbe4caccdacacef1cbcbcbcca366ccc5bccccb *d5ccd2fecec9c4ced1eed0a667d0ced6d0d6fed1d3e6d1d5f1d2cdc9d3d3d3d3d3dad4a969d4d9 *fed5d9f3d7d8e0d8ac6cd8d5d4d9d6dcd9ddfedbdbdbdbdceddcdce2ddb06edddff2dde1fedee0 *f3e0dcd7e1e5fee2b571e2e2e2e2e4f3e4e1dde5e5e9e5e9fee6b872e7e8e8e8e6e4eaecfeebeb *ebececf3edbd76eef0fef0c077f0eff0f3f4fef5c379f5f5f6f6f8fef8c67bfcca7efecb80fefe *fe21f90404000000002c000000005a019c000008ff009ff41948b0a0c183039f9858684207c287 *1009aa6168424dc48b0775501488b1a3c78f7dca3cd14871a18e271641aa5cd9474e4b39306196 *9949b3a6cd9b3873eacc99a5a7cf9e50820a1d4ab4685022489326b5c1b4a9d3a6302822fb47b5 *2ad53e56b36add4a351d49134fe4711dcb351dc57464d35a95a7d0245ab570e3c2d557cd535b86 *3a1c21132bb76fd57dfff609c647b8b0e1c3880dd75bccb85ebcc79023476e47b9f2b9cb983393 *dbccd99b67cfd8428b161d2d1ab3d3a85113f3c5ba356b58b063c33ef5a9b6ed4f983035dabd9b *10a13dc0dfbcb9c1f00957ac7eb7ea9bc8b05a72ad6619be7d5eb51a4535faa86b27fbcd15738a *7d804dffdf1e57f03ec28313ab57dfd8b163c9f0e355b69cb93ee7fbe43e831e4dda34ea2aaab9 *26a06cb2dd565b6ebcf5f61b707b08670545df6c851c7954b9429127e445b7d078cf7942912b14 *86988e2ddf31548678215267de79ebb598587bf1c5371f7df59d835f679ff1d75f69a80160c026 *cc10b39a80af11389b81b8e9c69b6f0b36285c0b0c4d689594145ac71076da696802877d2d4791 *73293e970e307d9454912b1186b9dd8ae9b9d8627b8cc528d98c94d568e38df9e9e78d8ed894e6 *1f33010c108003bb0c49a42f461e69a0924b36199c11146597159514b285579ac969c9655cdf7c *15969a72c9834c99253d812660a086785e9b6ebe09a79c90d1ff69276678eac767683c9e160001 *040c204015860e9828924926c824830d8e4111305a511aa223cb8a79d673c050e448aa6989eac8 *570b3de1493592624b219bacb68ad8abb04e26ebac37ea79ab9fa6ed9ac001821a00c9a188264a *dba28c36722c836fd8505cb3e222035ea6d37649ea4253899b155d9e70db9023e03a9ca2608105 *669eb9ebc1f95ebaf2cd38eb65edbaaba39fba12a0800209f43aa82c44260a0b92081aeb1bc06f *4441115f55399ba257c5f10c97a67db173970e9baa09f15d26e925b4c56a92cb22c72f7a0c329d *edb05bb2ad7cf2b8ab021330306faf02fc20ac91fbde56b382c8261bad553a609aaa3e0b9b00e6 *d009c365e5427d84ff9b6a7725f21dcc3b50174ed58a54770c63ba5867ad357e5c771dafca1378 *3001cbf40660af6bfaa66d5bbffede1c5cc0576675259ad85ac81086784b1797870c81f8b77766 *8697b4e1d80236d8d48917862ec8218b5c63ad26f307efd7132c1436cb2e3b0073be049ee2f981 *fdfeebe41191c25d3b8a61ee5d91df65e53d9697cda93966dd0ba9813aeeec6b4c6eefe73616cf *c772caeab87d5bef2739f227e960b9d80720db0f6e21b3e9e5a67aa273d217be34a57f006e7b4f *a38ea54c22b7ad108d3b9e8ae073e4412633a9af82ed0ba1c6e05735f95d6d5d76cadf9e24170d *fea9410d0ab11ce604558041e88b58a04ba070d28082d535b02a4b2b495efff6421e6831845963 *b92057aac5906b6d475b12f356c5444845f7bd8f84f88011fdea273cfc112f47272b8d0b1dd107 *356864792d1394034a81369a21b049c2214eb77ea81588492c2f534c8ec1a204beaa28f161756b *5872e8b2ad527dab8f554ce4c6b0e8bbc531ae8b295461185b48391da8c1139e70040cfd17b6b1 *f96a07d1a359824207c737408a21741c0b140d99c7b800ad5b1afca31f8f763bae04912243d460 *2215b9b17225ee778f84a46624b9bf4a5e1218aef044196378b979d1d086b0981ef56c56ca07b9 *ee2a7dd156031ec0cd6e7af39be00ca738c749ce729ab3010148a73ad7c9ce76baf39df08ca73c *e749cf7adaf39ef8cca73e5de8ff0960200318992ce31919c03c412d808dd15cd428ad271c6531 *44903e4bcb03e0e0878a5af4a218cda84637cad18e7ab4a3707800af464ad2929af4a4284da94a *57cad296baf4a5308da94c673a52b059b29fdfa8063292a9c991fccf930250c1ccdc68339cbda1 *870b61dd3f224a9607f821159388aa54a74ad5aa5af5aa58cdaa56af9a0a3f3c6065600dab58c7 *4ad6b29af5ac684dab5ad7cad6b6baf5ad700deb046e0a8c6fa4e31bff4ce6324d20436706a000 *6810253591f586a8f0ad67cf71ea24c0f0d1c63af6b190ad281826e1d50958f6b298cdac6637cb *d9ce7af6b3a00dad68474bdad29af6b498a5eb37e4a18f74e814a06434a309d0e8b205ff48426d *6fc4991c2b82d8e428f6a9a908ae70874bdce21af7b8c84dae7289eb07ca3e4007d08dae74a74b *ddea5af7bad8cdae76b7cbddee7af7bbe00def748ff90d49c923a73bcde4267f1a405fa9e073b9 *1ddd10f0d25bbffc3615c978867ef7cbdffefaf7bf000eb08007acdf6474d5b92f4cb08217cce0 *063bf8c1108eb084274ce10a5bf8c218ce3083fb80d370b516afc854260cf9dacccc01f6808305 *d8291752dfbedcf719e888b18c674ce31adbf8c638ceb18e63fc8c037b1593400eb290874ce422 *1bf9c8484eb29297cce4263bf9c9502e725dc1d7dad70654b6b435a82416aac33728217b4b4d6c *739f0a637a98f9cc684eb39ad7cce636bbf9ffcde8e8f1981f008c3adbf9ce78ceb39ef7cce73e *fbf9cf800eb4a0074de8421b5acfc828ef56ceab539eaeb793ed0d2a9771a63386488aa9637931 *3ae8910f7e78fad3a00eb5a8474dea529b7ad4f9a0479c7dfc806fb8fad5b08eb5ac674deb5adb *fad6b8ceb5ae77cdeb5efbfad7b546e43f3e9c57113373867fb582824a59e985f0c54cd086b6a6 *e9c18f7e58fbdad8ceb6b6b7cded6e7b7bdbfc50b59c9dab8f729bfbdce84eb7bad7cdee76bbfb *ddf08eb7bce74def7adb9bddd972ed3faf3cd08206e0001e887649de22f0829b60dad5feb6c2b5 *ed0f7f2cfce1d70ef7aae77cef8a5bfce218cfb8c637eeee7c5b39b6fd4ee3bf036ef02d61d3b7 *63ff4e45993b7dea968bdada2e8ff9a7533d71e702fbe638cfb9ce77cef39edf5ad8c40ef15efb *6a62655bcf49cd36015f30cd9569bff9e96aee34cc530df5aa9bb9e65e3db4d6b7cef5ae7bfdeb *60e773a211c9e8f4f6949300249b0a528c7430337d2b9adeb1dc694c6d98ab7aee78c7fa03a2cc *f7befbfdef800fbce08d3ce587e91bb6029d2d41456edbf83ae9cb963eb97d539e5f025b7ebfd7 *d874c2257e8dcb7bdec073d6b0e8474ffad29bfef4a86f30870b4f95a0eb75c444a7211ad6b66c *9cadd8042d96cb7d97cbfbe1cea2cc9b17f72c7a4f7c568bf7f8c84fbef297cffce65797bce645 *afa37d0a69b57f8ecba59caf49721f17c53236b21f55b9ffe6ed3e71f07b74b29545adfad7cffe *f6bbfffdf0cfac6a597b787e2bdedfb685afe3e3583ac9bbf8a95b158053c558e25777fd207172 *36590228805df55571f58010188112388114588172a55a77556c435762b247548d524a86650213 *f2765a3151e6d751514566e37780e276609475821b1552343583345883367883389883246553e4 *d568ea457d69e75e43a5504585334865024a458254a14de6d484dea40129077ce4376e7ea0014e *7885e8b44f5ab8855cd8855ef88560984ec6d44ffb0672f7c778086540fbf7060ec530dc5747d5 *5048b874487ef14a60910e083785ac960eb4e417fa800c72881774b84b846815bdc448f5904526 *144cc2344c90ff1339a32146632874b0c7817f054dd2447ba48433d6b4216f386c75c134134344 *cfb1477c931d79c8827a376c81244180184583588821842a88c3488a18278b013c8de888380289 *b822893c884967c75e64034ab29189d84758b7974afbd01da2e810a4a81d46b41048f40fa98880 *ac56154cb4104e9425a3e241eb238becb348b648188ec48834c28bf7513cc643493c6886591600 *07d546fcc276fc374788f54025613b2132410d2137d7d8827366159d123422d24125a13eb5248e *aab248bc4342e7082bbb48325fb44293e44295886c3554401eb889a373543e54151273260be917 *df701de01390ab68155ed2001af09230199331d9005ce19232299314ff001edc03178570933249 *935b61933e399431b9012b4006bf206c5c81316440944ef99432f900d0101f24009544b9011f00 *047d500cbef88bee38574008546623333884406df3065dc04055713a201422aa93547017852b88 *8d03a9159ea00193b05c93a0015c8197c8350923c007a22882d1b815cd300279795c7bd9978959 *7ca9600aa6b05845a0014bc00d7db10f5c00068e597c9ce00253091f24a0089b195c91e9075230 *02206008b7d227930336cab378cdf33c9d23581f8833d8137922a968d842376a598272698074e9 *5c7d990a520006c6799cc82905a9c0975ba101c4899cc789057ea0081bc05aa128444e9315f2b0 *018ae00758009dc6a99cccffa915ce599ce0799ed0f99d7e009960e00240000f7001185c2059e8 *599ff6799c52600a9e49958b759ff6e9079a900a8a10041b500993f495b1a739f7d21ab3598fb5 *393a02933e93e23076f804b7a39254f800c309069c705c9ca099e39915cec9a1c5f5a11fba022c *19877744872bc0a1244a5c1fba9c1bdaa1c507999ca00860800593600a60b001bf9016e6319fcd *359ac9c5a3faf9999241028b15a08e690a9c405960500702ea0229e00c91e83594138465e31a04 *744344f8a04e92066ff38914628a22a894d6f89bc1b792e4990a9a990cd710a7726a6020baa1f8 *25a771ca0b9c8005c489078bf68a25d101ca89059cc00b787a0d742aa3cde9a677ff7aa88e7aa8 *cf900cbc900a9ce09d4fea02854016415a519300a78ffaa9a01aa7cf300b6070a4fcc9a19e1aaa *909a0cc2c00b91c9583cba01bdd01f29b33222e73c31e3a56a334aa143693b33a1a9328d26508d *99a6a67a58976daa9999e70eccea0ee8700d8c1aa25631a2a9b0acccfaacbc80a3faa90c64210f *c1d0073a60012ec0a38a60a8e8d0accf1aad766aadcddaaeee7aade8200e883a0b1fba9e38e0a7 *5ad14b42daa9e2f0aefefaafed8a0edb40aaa60a1f20b0589c900ce70ab0fe1aafdbf00caeea9d *a65007b2ca9afe212f99b339f8428fb865963813a16041306ae28f710317189a8d8baaacee900f *2c9b0fee00ad759ab2d5bab22c2b90d3ffb901f09916f0a001dda9829cc6b22fabae327b0d34db *b2467bb4464b0fce8aa8a6e007a58a03a49015bab3a9cda5b0f680b4589bb52d4b0f035baafb69 *b008abb05aabb557b70dc9300b08eb071ba00bb90228bce22bc0b2b1ba4a3d8ee7364724b229e2 *3d5862b2c6aa8a19baae2b6b6d2e0bb38a9aac339b0f824b0fe2900c3cfaa124a01624e0a2a690 *0ce2c069821bb4316bb8448bb8107780a9e60e66db5560a0091b609987a33b85b1af569b709d8b *6da9d6b5059ba4618b0e9c0b71fc50b3d8faa13c0a02ccf027813228bb1024721b3dc8688fa604 *66a9441e6f8984ff475905b8a67f3bb481db0f832bb49a1bb80ef7bac9b0a7c4490664410683ff *9ab0db60b9d98bb9cb191eec20a28cbab9fde0709d7bbb8a0b7a94f501f88031e4a2bae8600fed *dbbaaecbb504fbb59271b0a84abbfbfbbe34770dbc90099a290561f0273e020941122c9c33b7d3 *04a6c2f10650725878bb1dbc593ecdebb3d08bb2d7cbb9d59bb9eaabb2b57bbb2fcb0b8ba59f3f *ba15bf30ae9365a82bcbba25bc9c78919dd4cabed43bb62dcbbaf0bbb83c9a0a41b00a863835f8 *abbf9eebc3640bbb2eb00c73d20e029cb004bcc43eccbad46b0fd88aa39ca001baf01fa921c1ac *d1a5a1d4916c333a9d68026da98449e429e93b79ce2b857e2bc2277cb8974bb81ab0293b3cbd30 *a7c5d0caa91bb00e5ab10e1bf082d59abf587cc31aff601742b4c724acb4007b665257bedbc0c2 *93b501f59b1e2c92c476c7b00c2bb0ff0bc5ea32c5629bb80c2bc9889bbd2d58079a000642901a *a721c60c4a960eda2884351c032321e461a67d2366713c9702299cd24bc2e6ab0126204855e1c8 *3097b8423cba7540027ea30f1fc0caa54ab9967b80772cb4f300a826a0ccd4fbb2a1ba0d957bb5 *7dbc6a9a8903cd6045a9cba9566b77f2aaaa9f3aaa5e2bcac123c5b3fbc8dba0aae2b069b59b6a *8bbba75d1cbc612ccbd0738c999843a594960f751cdb21acc40ac7207cacc23cc2d90ca2dc58c7 *3cdccf5cbbbd0b3c05563105ca89aae3dbcf155db855e1adde5cbdc8c50bc9b00d889cb895dc9d *75b004e4ff48189ccc82e230a9a369a44f1c2b9541ca55fcba3a6d5cb360a895dbcf415b07a620 *057730d0c3cbb1f065bcbba50363c1c66b71346da97b7d1b9c5e05b8c48cc7064915298dd4083c *0958600a3860c4ffb00a38600a3a4ac3fdfcd5d68bd1d35bc2e8e90785cac3fca0c51ccd0998bc *2a8671d3e196d34eeb9fe7999f3d5dcff63cc0f83c0b850d9e759097d6fcc8393d0976e0072ce0 *d44442c6c75896c6bb4077cbd0c9a1b768cab7bf0c9cc1dcd5c35cd21a50226092d2d7bcd7cfea *d87130091b600ee650c871e007b39079f69070a926d7263cadeb5bd7983bd4c315b6475dd223c0 *0e8921d88acb0b784da49d49cff301d48dad99c655afe2f7db82ff8b0e8c7bd61a400c0172281c *499bb63c3a3f405f559d1ccbab54db71b2c84ad7c22da3b0b3102002dbde4dbdf1eba6f3fb01cd *f5a6cb7d80f670cd8aecd525ed0232e902788dc2304db038400dcfcdcef9ebced26dd656e9930f *00c57482dd0ffeb437999f6050ae239db884eb02ad10cb04dda0b8f5d963aacb72413e0b7137e4 *21df134ddfac4d157a9bd2ccaad1ffac9958c0a7a83ae0df6cdc788ce0df8cc777e10116a001ad *4cc59c1b6e958cd752f00b135eb5158ed3172e05ac608e11192358e3e1fcedc4b9a01fce200441 *e0a6a60063f8cc0b75c00941f008b1fcd49dfda5cb564a206b1c64a18415aa4bbe1cd1733cdfc4 *ede0496ebdfec8e344ffeeb295bc58c135c3dbc0c7fe6ce4733de8765ce8753a0fd7190114aec4 *52bee55d8e18d04dd893c0e5c0543f8a4d1962febaff5be6b6f20138daa955dce954fe074242e7 *b171d075fb06694ce330ae16c1602da062e3aa4dd1966ed2ff60443c7e0d032edbd7e0d8c6c9db *be0ddc8a9bd1c58ce4076e15e950c8609009a5cc8253ce09557ee5b0cee9d1dd5ca4fee5602e2b *a9eebf5ecbea1629049b6e77533eea6b20bce64dc1c562c14fd27f7b0e170e9d2ac2aea1ab5dec *d2fa0fd592ecd19eb8e5578051eec7d47ee403afc82430f113bf019aa999cf50d75cebe6a61004 *cd20eeedace5e6be01145ff2267ff27c70ea97b1ee64ae3fd3a0ed502eefd2ff0dee7f802f057d *eb3493efb5373ab7e7e764ba84588d2d016fedd5ae15df90ec702ded423cb9cb3eb8709de3118f *b9684b5590f9d6255eec2e8004a0600d89b8ce584eee84ad094fba805105065380352b7fcf1fae *9f94900b6eff0aa10002215de9aafeb48f60eb8a52cb1ea9401f02174c45dae232f4510ff1c45e *bd2d7dcd63ce0bbc70f5636e600f3fe9c95cdcc27d9edf3909e6dacfe0edd6a6a001247726da80 *0fa12edddf69d8c84959673f1f99c1f2041b042ed0faad8f03406ef9577fc3288ef70965e7bd0a *300d12827aae1611f5de1623f8855ff4c30fad4c1fdb0effd2fc2dc4744ffc385ee89c10fdd21f *fda6900ae66ae01bff822c403b81ff1aef5a3efde01ffed3dfb3a75f27a9aff6634eaa9c0099ec *0f9938aa08bd5dc5d40bde00bd01b67fd0c9383a90b71059bdc14004106a4c0c3451eddf418409 *152e64c8f0819f497e523d43478f5fbf7efce8a17b960aa29f070d35a40293ea9abb7c18f3b9bb *46329506912e4fa6ecb7b2a5c46b152fd6dc5891a64674374da254c9d2254c86234bce2c7a2dd9 *53a8509f5d13e71323bf7c41499a0a420b1fbe78d640511918c10fc464e8ec5da5272eea5bb851 *7945f433a5dddd7379f582980486535a9af9e86d9be507cc61c460eaf8e1c48b22bdc08379293a *9bc2d765ccbe606de60cebd427d0a141636a54ba3421d47b54bf79d385a0094f0d19f659ff184e *07c127f264efe6bdf061c4893ad972f41831645299446b1a2d8974a1d2a181994fe23573a760c8 *576dce5daadce6d198dd23a3235fde3c3a779053fae3b98dbba60df3becec7376f198bb393d2ae *cdd8f3fcffffdca2cbae76f432902fbf005349b2591a74b0415e784926a7ec54d20a0caefec8ec *b2ce3afc4cb44f3021cd34d408516db5345ac0adb784684b0898d71cc187451a77fb4da2c77602 *aaa38f8e7b2e39e95a6a2ebce89a22c92f5eb6a9b0269adae38593c38a5c4ec89788648ac97cb2 *d4724b2d315ad02d533094a210facae422bffdb4e3724d36374a664003e344f02f7422dbe64e3c *f3bc13bdecd813ccbdbee0db10b30e37fb5034ff114d6ba44413577b6388d774abd1c57ff071e4 *35606ad4b4a11b83b368381e8db3d23be6aa444e3c2331c43019712ae4e7bab69209334c29bf1b *f2d422d9f372575e77c5aa2d1e218aaf4cface444bad7e74ed75595fed41e7cdb3ec8a73afbee8 *8c8c1e6cb3d5165b7bf2d98927b7b692a289410b3514c410472431b513dfb0e235643675519e27 *08d2219c4df355a8d31c412d0ea45183040fd72b6d2d0c47abbc148cb8b3664175ca817f445559 *66fdb15861c1c4e1d1af0dba21763e63f543966266997516dabaa6cd8b9c3915cc884d2ebf5d30 *a88327d940960dcd3d1444754f63770fd6be88315fdaaa794d8d79f455fa207e85eb8f61510926 *954affe71482aee052a154a4ba3a75ccea9ac9fc023255532596122b98b594f9d77021aa63858f *bf0a39cd97d34efb64385566b95a0549ee95e45f839a0b0b53705823b35bccf50cdd7415fd19e8 *375224480d7dfb00e5b5d8965ebae94f9f0e1560a905bed56caca99422152ca853d2cec15339fd *615bcbb67a6c9eb6b55dbd8bfc8c95132c52c10198b8e746b6bfdb8bd7f6d9bc572667f9bd13ac *33d99279459b1e77346e5d8a10caf590f110155df467d6deb0c15e4937bd8d208334dffc234f75 *dce8731f6787bdd4aa13ba7a6a974650d51456d58b7556308c8076b1ab1f42ee271d3d25b02af4 *e896c2583299b3c0ed63c2e38f46c491400ceac929c953defff25af63c2ca5ed2af6688b5352a1 *88de810104382394e27696ae9e7def4490831441bea134dc944f7dfae29cfba0063ad2e16f74f2 *ab15fd1e42194fbdcf2394d9c001c956c08338714abc78d08322948c6d248c1f27a3d508c241ac *7a50902de2a06215cd7846ba744015d33807f398f7c1f100482db0da86304c6118d46120169849 *9c0bd195a87581ef0d4780d7d20622a31d6aae87feea51c09ee8488835c70223d0da2c72423345 *f86504d490220121f91dc324e6307e508429b8660f58810d2258b0047deaf14a31f6878c991465 *2d6d7996080c44078658e31bf906c23fc56575dad14a8ff6d8429dfdd17b8c6a97bb5ee30acd99 *2053895424fbfaffe5b97fc5cf7e03a4df27e9078c0ee00075aa0354ef7060897f74b29ba1239b *29dcf94e4e18863a57b2e09bc0e00716cca71ef880259a8667415e90f29d032568413dd281f311 *84077f78c5077ec93a4e4434a2fc6b5564c0549220908b433a7b61f79629c82d604e7d94a36635 *8173cd1d65d39b545b2978c2110155fd2519500a1310a2c84d962e641feaa4120e5cf0d39f0641 *22096ad5759e650ac26de02baf646a2c010a11300055aa53a5aa0b98400e67a8c20c28780d041e *ba20c224060b38e91a58dfa3815168c68f3cf3def71a05b92e707520945a1a5d4b9aaf4562b391 *ec8ca4ecb639bf9ca6a3026e4b452aea10910ddce3a6808d1842f6b153ff9c1e851b93ad46357e *b1013068c20f96ac1001d5c1d47ac4231e53f06705db12d04948810fcb606d6b5dcbda610c2317 *b3cd8534dc488e6284a20c26f0aaf3ece4b0544c621224519dab9cd591c382a1038a8305e30019 *c866c6952076551a75ef5aa3bca674af41149d5f0d18d9d17143039ab8a761e0c38def32f656fb *38c86321abde97102b1c1b40aa299ee11d7a08c9142e0807685f49da6399968c10914227ee72e0 *02a94c2fb7659e37bc810d0c7cb53d0edbaf04a430abb4742e633335a7190ac5bde7faecad4193 *ab0948ba43eb5e9745d955e2768958bac6feb588393d0829c4890573a233bd333e0a7bddfb587c *f0f4281ffb004d5d26986b50ffd805d678a568450b60910918b5053eb0823bc8600767d91b7004 *ab9243b101ca6cf64a5354441c6c568ace7434c4eb6ae6174a7c6214ab9887d6749a76a3c6dd47 *f2d5930959c2e95c17011ddc70b13c6ece8fdd1b64f0c6b74cf3a02fe1ee1b19fdbaa01b4e7632 *94e9f6d4d41a38c10a667083b5ec602e4f18432e0881095c80d44c60d1556e2209945260a88e36 *2e90237e839b27a78f92a658ce36a273e7ec0cc4170bd1bb8386f110ffa18f0f9ce5011e18c834 *855ce8af00f92bcf56f47cc2c1022940c9249d2dd508d841e92797768c53ee8495178ce54f3f18 *1ba1fe9392336002986a9b22a834eb2408e7022f2c4e998e2b5133b7f0e6ebea7ad7ff9ceab50f *e1d75263efb8d8defd860634d089d71802d1f0d580b4e9436d17385ce3fa1b272f8a6aa167d477 *03e00e7780c7bd4a8da75ce52b77f80372a1656cc49cdd8351f21acc60020df4656b63b6c9c1fc *b0815238b7adfd76d4155e23f0ea0e5c532cfea136152e6c28a633d15064052bfe611bdc505b03 *717b362f0afbf5c26a020b8ab02408b7883c30288204241fadb86519504e805dee73973b275cf0 *7275c77cdd126ef7a84571192a8893a8ab3eaa9862f0c79e11bd5def9aae9c91aef48430fde07a *5e279efb1a7584cc432003d13ad7c16bcb7b7262168f611d540bc1764bfff3b4a1047debc170e1 *bbeb5df6330feb7eff7e191080e1a473acff3786460088d0c4d0ad33648d1244ea78c8d348f22a *a53c8d83dd5dcc23041f97c3f9d43dcf58ba17564214fac9715de28265a0deed00cd7ef9bf3eab *d8cb5ee67ca7b9df31838a0d40a9b83ff9dabf3080095943773540ab61b307fef8e4fb87e57331 *195bb8a8d33a8530b41f339acefb189eba06088c4009dc0671488ff570129dc300b66b3b939325 *09fc4010fcc06750b25750bff5f3ad2e733fcc6882d7a1a8cefa1f8cb2002f08848fa2b537b881 *d7489f5d03c0e41bc03b7bbe3cb3bc3dfb87c76a2f43fb0a76684062e924ea7107277cc227cc16 *6f511818e48a4e00b7bbe0c028630b28ec422fec4274a83d172841f58b06da53b2dbe3100c2025 *ffb29a420ccc2c0d283513b0012fc803c5638d318081d710b4ff4b08f60a40df283846fac10284 *3a847b893ffcb1683b42252c934eb21bb5d99585b989b3c08076a034044bbd0a8244bb69bffd22 *436c8806513443f613c334d48c4518813099bf11228ee49280d7300114f00125f882d5b88212cb *8de4eb03052c42220444cef196c0993c21ac3c20bcbc7d88367cb0b825b43e071c1bbf899e97d9 *08b0e98bfdc205d142b003d344e891c692e9bb4f0cc55164066638c351bb848dda8c19b8b055d1 *89c0011bb1f31d1b38831f28b18140811be83f13e04114ebc51f73ac3f9433ced996a63bc4039c *ba648c9b66a4b8eb93126ff412ac2021ebb137d72103ff27d3c6bbd0449979485e01c7311c4772 *2cc752543274ec905200b38699097ba81eb0b9a31482003d400d3750821bb04782802640ec0362 *51c465f4c7440cc85fdc94a60110627c3e2de9a65e3ca0a3a41a857c46f158ca2173cae8e0442e *c196304c86134a211238078cac324da44a48f4c48f8c8690244738d212b12cc90e618353c38254 *5392a0c04a9d330529d88021781c67ca41403c089d544869f349f732425fc42ef6498667384cc4 *3c4cac244085438f27bc10444c4a99704c2784ccad6b4a479c4c28b4cc86cc892ffc4c77200f71 *700a5eb8a39200830f1887ae34104bab40d07c4d3014c35728cb90fca0cd14c345d09914f08b92 *78866d7886ff27c1233f7081128849e27b8328381a1d0ac0bec4cc9e5c44fa004cc12442436baf *4e31bf6cfa49f7828e09f940ac2cb4bf4c46ee04c1efac36e79cb854e84e092ccfcb7425f454cf *100cc16748062a32854c2a2529608172d04695b1b4f8fc4f001dc1519b4dda14c904014101ddaf *dcdc9e48d8009d9390ac9c044e9082085002417a831f38bebde4cbf3fc98f05cc4f0044cf7fa8d *f23a0b133d517902097f548ab8a33b6dab38a76cd1b97bd10e9db656cb3e1a75a5576251ec9c3b *77e28488182b8f18013ce0ca2a533028eb5125053bf423d0b2240604d184ec43bf053d97d07002 *c18ba828a9830d78813d782bc8f90215419f0d6d911a3dd33261c6ffe87cac87082ee17a533885 *538f788084cc4c2970bdd3694f3bc553f374ce91b8d3d6cb53ff62aa3f75bdd6c382d0bb231c00 *8161a8b24debcfb3305449053dd8735272240628ed0b3c5550ce609cdceb0b2c00521ca0003400 *d3f03102e52c53334553563dcf078003148d5514858307e0bae1c2ce49d0d38bbb55f3cbd533cd *b91ecdd53e98874105d625655253e88bba64015b403073d38b292889639dd654b03b51084962c0 *0c1050841eb5bbdc8cb54f1884f81b2e30d8801c781ca0c9434c51558568ce567dd78f69800798 *577aad577ba5d706889b06603996cbd778e5d795f3d70edd57804db90630011ee8afd0122d822d *5880dd001298024f0007ffbc78d60e620287cdd88c7d806bcdd6cc00018dd58007003ea16b841a *9082e1e4003bb441e3cb217655083980579925960020000598001d50034f00866fd0077df80660 *f00435d081095000020880994d5a991dd4575287dd228860d840a9c5c4aeacd867edb406238774 *cb3b131447b22c50daf4d84141a664423c7589800d4802305d8d2f9081677ad9858859a59dd99a *bdd99cddd99efdd9a01ddaa23ddab9fddbf3645a4a0b2dea1b084a985a92ab5a67b558ac5d9ead *75b0ae8db95124cbaf05db6c15dbb1652e7ddb3745418398b44142c28d7480db852803c085d7ba *c5599de5599f055aa1255aa345dad3555aa6ad5dff023763780d2a0087a9cdc2ffaae54ae0bd5a *ac7d5cae35c1c9ad5cb065064c1ddbcc602e701591c49321e2eb023d248869225d8530ddd965d5 *d4bd5bd6d5dbd7ed5bd9ddde1add277eda27f4b5dd8545dc7800877a19081a3006b653dc4765dc *c6dd5a6c28de3204c9e4555e5fc05ced71a15883de8f9a21c8799454c5ded205ada5325ff2fd98 *ee5dddbc755dbe8ddd072e5ff51d5cf64d5c44788d50b844fa3d52e16d5cadc5dfc8f55a51ecdf *4b5d5ee6552be672aefc13315345ce12d381785160862883416d601ebee008c6dbd6dd5bd8f5db *0bd6d10656df268b8724dee00d5485d7280375f8dde01de1e17ddc13d6bbc95561ff6de13e7a61 *106b2b9f39ce2e705b82f0045cc3e1ff1c4662ff72cfbffde1efa5e0211e5fc055e3da65623bbe *c876908684e2016910618b6d2312765c133ee12cd66200ce5ccd0531e11bbe664a037d5483d145 *e3862803275b583a665a23d627078e1b379e6021165f3465e0f3bde441bde33b56dc7278da8150 *853f3eb7fb1de42b2ee4fec5d443ce19cd7d5e3056bc0356821abe61499ee4a9052dd12265a6c2 *074a0080004866655e6665b659d50562f0ade0a365666a0e0000a0845126664b662a53b6e310ae *b2c2358144a0e22ab6e25896e5e4a5e5164ec7b532db1ab4412b18d381708533fe6560eee64aa6 *e304180002e8677ffe677fb65b090ee2f0355a803e680218800450e3615e5f25c66753fee6ff04 *dbb45e28312ac8863809644ffbb4fcbd62144e612d5e67b2f59053186002e637bc7c832d20e343 *5a4e7b2e5d8826b9255662a632869a4d0005c8699ddee99c7ee637fe649e0e6a054880a3955f9a *5edf998ee9889668ab9d9669208b7bec054026616f28618ef6e85044612ddee275d65ccf30e95c *d6e5a0c1c1c989e497de0d4a566a2616810138809b9d00b88e6bb9f6694f0edfb9be6b05388001 *1001b5ee6bdffde6565e993f780d507865e2c56aafdd6a755ee72e4ea6e75d3346769431c850dc *d0c1b346ebbede6075180085660066d301d00e6dd11ee868166dd3be0d0f60807d1e0075c8ec53 *0661a6aedf3f661e27268832c886db32678f3edeffad2647911ee9ede11e8f7ae7e31c037db4e1 *cba691b4be44d7dec044b8e9093081275003eaaeeeeaee036876dd3eb06eeeae970920ea004884 *e6dec0d85edcc0ce68062b8684d28162205efd8d5c744ee75a0ee076e699e146e91936eed7d081 *eb4deede2803fa1def784080b6166847f004044ff004ff69056f7047a860bd4e0001cfc6f236d2 *f39e168dce0655360155b8eadd8e6ff9fe6d76e62845163e666aa6c9deeffef6efff2e6f0ac767 *9b268004f0ec27c06e60b8711cbf7164986064c8f11cf7843e7882d4066fa346dc2cc4c2f2e6cf *0bc7708d765cabae84d7f803c4fee8de66e1dff6eae6126ed288a17e9be12fa06c5d5a7116ffef *e04df2ffae4c5ce616ad0b28f0e856034770851dff06399ff309a6f339470657787013285abdbe *00aa3d723397e20269ea256f72377adc5ab0e8633867fe55e1c5e6622c2f692d37715d5e8d2d20 *6b5df2e531af913288133f0e74c51d07ce9e710ff0de6a480779f059553f0855f7597948876a10 *e221e76cd504758cd40bd95e72573674abd6ed63806a594485fd05f1e415f111f790cd45bcb04e *69776169e9d6f44de7f456b6da234df23f806ee9c6ee1daf67d9f859640072ef06ef3f48f2bcf0 *635de7345e3f742b7eef501c6c82a884e345de599e6f44765e492ff1653f4ee4acde8150033e8c *f64de9f47357998afddd76300036cfd9374706b3968d74c0f3ff07875dbd368082cf755c1f7874 *9f6a43776f989bf250780d283886dec65663c7f264e79945ae74c8190323b0c73e6878800f7837 *521e8cb7d85eb8691ab7f16a70e98490875807f7213f5aa9aef9f34ef74ee378c89df2e3d5051e *b0975a98772b17e94817eed168044a4757d6e8821d88454fe0f998e77412a679a237903577eb36 *5ff89e6d086fcf7381e0f301b880b1cfe82b33fa12ee75589ef28fa65c72dc852c788d47085be5 *a5775bf66aaa87deab67f628e077e916f3afcf9732a07bb1d7f56c1875cf3675984708589775d5 *e66c8c3ef7e5997bbaaf7ba44f7abc975c620f4941780d33f085c02f7993bf77e7826c46595ba0 *f9822170f97f6ffcffa52903070bfdd037906b97f1e8ae714fd8f685f07670df73717765d0f77d *aa1efd9863f758367d901e795428311e3826a93779aa8f61fc3660c8b10267d70157f07add777c *f7767e434778b3577838bffc87677b891f0003507f5e1ffd2c8bfed2c7e2786f74c506085fc464 *513161d004245f0a172e84e5f021c487a73e4dfc64f1a2454c1a3135eae8911048427b46927cf3 *a6cb1014074da8a9f6ef25cc983267d2ac69f326ce9c3a6596f1e6f327d0a03ec9012567f428d2 *a44a8dd60a402001030f4ffa7802564d5e4c79d58079eaf3c40383040402d45a6af62c51a16ad7 *626bebf62ddcb86da3cd8d66d72eb3bc7af7f2d54b4c2043856b56ceb9d5ff30226258a716636c *fc4963238e1e3b86044972a4c9374a60acd4e109ebced0a247931e9de5adcfb66b57ab353a94e8 *d20b030e2898c0d2912b64dff4bdd4f70d992b476a4c4c507060c005b3458fb26e1e542e74e874 *b1ddc5dbf77a5f627fff060efc68251459891133767c71a3e4c995455ece6ce5c64a137d5c96ae *6fff3ee9d3d1517b53edfcbf4fd30c3000541ee8a04655d5a4f3523a5b79a2860e602530e03400 *02e8df7e19ca555d75d879e89776dc7537a242a3f070100a8c8c375145e6a137d947955db64766 *5ba4b4d213c0f0861f8f3dfa18937e1a0a890d50fe35b7865309d8369527bac923cf6f5d3d419c *5801ac612186436ae9d6741ce2ff65dd87d711c34c88249a19912c50ac2408442d9a97517a30ae *3763665f18d142679e2cf8239f7ddaa7df745b0aba9f01b3d576206ec8a4930e70c2e950dc7106 *0c3aa9745e76c80c986166c79d88660676cb780fb5b152156f9ef7188ceac9d81e8d631cc1d94a *8e7ce327adb58a0685a577513a282a4946c5a4550e7a25e158a8ec3a69ae996a8a9d76647afa6c *a88941a292413c44e2e246a93632677b268d6104ac07cd672bb9e5de04455f5f26cbe1b16ec946 *9b6d6a24dae870900ee040bbd455a76fae7a29bbeca69d3e4b62b4e36124490f2b01026764da6e *6bd98c98bd6167b806f581cc8ee66abcf13fe802ccd7baebd635575bc7084060540756ffc51584 *120e20c03124eb3b32bf21fffbb1a621ea3cf099059367ea2755aca485c3db3e0c319d36e2b9d2 *c51973fc74b91ee33c35a636475345924b5225259563556175d57bdd4cb5873b03c673cf3e4ba4 *18d0186172c64a361ca26a4811d3f886153f502b2ec650fbadb1c763923d387685c28ba8a3f61a *4038e37c09be9d766843ab769b8b95d7f68b8de4b1b4092888b12a9d6f8ca1047c79cefa37eae6 *42c190cead37fef126be4ad5c7b0618db5c9eb00b7ae50e4920f4c796296b70d67b6a91e62c34a *4a846ed21543546cc213aeec993af5e4ae2e79eb8f0bfeba0386c65baf71f7e64e66f665fa2ef9 *2da0c2e20bf0950f7f5ef1dacae8c54a3764ff3631e97b5b8c0c68d5fb6febf5ce67a6de11507b *796916f9b4238b93154807110acbcb76a1b3031a907cac13980033d8be9fb9c954e8e1489ce4c4 *ad91a0616f2d88c20f3867902778e274ff7b2100332843b461ed29b6e95a00aa30c31dfe6e83a1 *12defb3e1842ba81ae2426f982fe0ea20347f00f864eb4de7878c843c3d5467152dca10fa365b9 *0e62ee8345a3ccd1d8b33cbc392f3e2c01c6f49ea8465a41218bebbb228920e12bdb052021701c *911b8107c4f7c10f325f0ca348c45812cc8c210a658c8f1a5ce1c23532925644c8e306cfd73dda *84cf01e78324266161112e7631737f5c0fd2ba7544d2a9d020895c642353e927229c2293ae8c48 *29ff1838210194e295b654cce5f8d8184f7e9110942962e8c6608521c8c08c3ae8031a55a94c72 *11c13c6eaadc2da37502a78ce504d1fc612b71b9c95cea124e8ff1a31f7b094a411a31335730c2 *0d9208bd26f56f99ee7464372f02c42d92278f8c18d0805464cb2d6e319e6fc2441f413844f9fd *1298466c9515d0594a131c1318bb792744c965037f52b431e5e1674516c388090420001360c436 *fb29cf8c72b2a21e14e240c53942bb99e46e5f48e80d16ca12575c25a2362d970d1ad611219ab4 *a7160984090e70001380d4a726156264525ab471d6cd6e77cbcc18ae70841f3ccf20c7a4693b6f *aad55ae5f48f9341a946e067d49f9ac0031e3041208c1affd680662e9c5e4d15539bead4fb89ce *0a5395813aa1e708873a6dab7eb5950d42f2d62f8275a7603d2c40817a90b422f6b08605a75207 *1b5783d249626fd842148cb083aa5ab50fb949e35f438bd3c95666b0a67dab620d1288d3b276a9 *a495ab536964c4316056b330c82bf43caba8be8ab6b7388ded1e5e0b92820eb7b5a94aad09e860 *5cb81297a923a16c6ce94a5bbbfec00632b5aabcac025adf7277633668e9dd801b5be192b73262 *58c9e7040b48d23e1794e2052e5d45b7052b2861083790c175b1bb570575b7bfd433010c6cf083 *2128210a56f8c218e29b99f73298c1e73d88181a2ce1b95af67e637869148e3084eaded68cf141 *546ebe9155fffb9218751e5e090a5a00831b0cd80805b6c21610ac60f0de6fc22379b041226ce3 *192bf8c2f38d82128cb0e11bc0a005b88dcf13e4e50aedf2b6c44eae9e3c1a048ce0f4410d533a *f18953ac6219dc6007031e82118e5060035be10a5b10c317103c8635a7e17e5658c915ee978635 *af39cd62d8c215ac60852800f90842def00eee5b642363f9c449ee036eb43be227331aa2fa48c7 *37aa818c297bc2115ed141a133ade94d739ad33a988a233cb1646454e31be96872a353dd687d44 *f91b919ef4945de1894ad34e0db67e02ae1d88e94e5bd581b84eb2ad69176a512f1918a476753a *e4816a5533bbd9ce7e36b4a32ded6953bbdad6beb6680302003b newhex * rmfile ./doc/summary/logo.gif hunk ./doc/summary/menu.html 1 - -
- - - - --Timber is intended to be usable in many different -situations, ranging from embedded systems to -standard desktop applications. The interfaces -between the Timber program and the external environment -are very different in these cases. -
-Thus a Timber application must be built for a particular target -environment. This distribution provides only one environment, -the POSIX environment. Also this is incomplete and a more complete -version will be provided in a future release. -
-module POSIX where - -type RootType = Env -> Class Prog - -type Prog = Action - -struct File where - close :: Request () - seek :: Int -> Request Int - -struct RFile < File where - read :: Request String - -struct WFile < File where - write :: String -> Request Int - -struct Env where - exit :: Int -> Request () - argv :: [String] - stdin :: RFile - stdout :: WFile - openR :: String -> Request (Maybe RFile) - openW :: String -> Request (Maybe WFile) - installR :: RFile -> Action -> Request () - installW :: WFile -> Action -> Request () --
-The root module of a program targeted for this environment must -import POSIX and contain -a definition root :: RootType. -
-Here the type Env collects the services that the environment -provides to the program: the program can call a function exit -to terminate the program with a status indication, access command line arguments -through argv, the standard input and output streams -as stdin and stdout, open files for reading and -writing and install listeners on files; see below for more on these. -Within a definition -
-root env = ... --these services are accessed using dot notation as env.argv etc. -
-The read and write on files are non-blocking operations: -
-Because of the non-blocking nature of input and output, programs need a way to be notified -when input is available or output is possible. This is the role of the listeners; a call -
-env.installR env.stdin inpHandler -
-installs the action inpHandler as a listener on stdin; whenever input -is available (i.e. the user strikes return), the runtime system calls the listener. So, in -this case inpHandler will typically start by reading stdin. -
-Execution of a program proceeds as follows. The runtime system is responsible -for initialization: it creates -an environment object with interface env :: Env, applies root to env and -creates an object of the resulting class; this gives an interface to the initial action of the program. -The run-time system executes this action; this may -lead to creation of more objects, scheduling of future actions etc. -
-After this initial computation the program comes to rest and -reacts to events, such as scheduled timer events or IO events on files with installed listeners. -
- rmfile ./doc/summary/posix.html hunk ./doc/summary/programs.html 1 - -
--A Timber program consists of a collection of modules. One of these is the root module and contains the root -definition. The root definition must have a prescribed root type, that may depend on the target environment. -A Timber installation may support several target environments/platforms. -
-The other modules in the program provide auxiliary definitions, used by the root module and by other auxiliary modules. -The compilation unit in Timber is the module, so modules may be compiled individually (but see below for dependencies). - -
-module moduleName where
- importDeclaration*
- topLevelDeclaration*
-private
- topLevelDeclaration*
-
-
-Here, as in many places of Timber syntax, indentation is significant. The import and top-level declarations must be indented at -least one step and be vertically aligned, i.e., the first character of each declaration must be in the same column. -An exception is the (common) case where there is no private part; then indentation can be omitted (and all declarations start in the -leftmost column). -
-A module has a simple name, which is an identifier starting with an -upper-case letter. Modules are conventionally stored in files of the same name with suffix .t, i.e. -module Dictionary is stored in Dictionary.t. -
-Projects and Timber sites may use hierarchical module names to allow multiple modules with the same name -or to indicate structure e.g. in a library. Thus, module Dictionary may need to be referred to by -clients as e.g. Data.Object.Dictionary; it is up to the implementation whether this module is -stored in Data.Object.Dictionary.t or in Data/Object/Dictioary.t -relative to some installation-dependent notion of search paths. Module hierarchies in Timber have no other significance -than to support organizing and subsequently finding modules in a file system. -
-The module name is given in the header, as described above. - -
-A module may depend on other modules, i.e. use types or values defined in these modules. In a Timber program -the dependency graph between modules must be acyclic; no recursive dependencies are allowed. This means that -modules can be compiled in dependency order: when a certain module is compiled, all the modules it depends on have already -been compiled. A compiler option can make the compiler decide on recompilation order after a system has been changed. - -
-Following the header is a sequence of import/use declarations, i.e. declaration of the modules that the current module depends on. -There are two forms of such declarations: -
-Both forms of declaration give access to all exported entities from the named module; the difference is that in the latter case -one must use the qualified name of an imported entity, while in the former case the simple (unqualified) name is enough, unless name -clashes occur. -
-Name clashes are handled as follows: -
- All the entities (types, defaults and values) defined in the sequence of public top-level declarations are exported, i.e. can - be referred to by importing/using modules. Entities defined in the private part are not exported and hence not visible to importing/using - modules. In particular, this means that the type environment of the public part must be closed, i.e. the type of an exported value - must not mention a type defined in the private part. Imported entities are not re-exported, i.e. the import relation is not transitive. - - rmfile ./doc/summary/programs.html hunk ./doc/summary/simplestyle.css 1 -body { - font-size: 12pt; - font-family: helvetica, "lucida grande", sans-serif; - margin: 0; - padding: 2em; -} - -h1, h2, h3, h4, h5, h6 { - font-family: georgia, times, "times new roman", serif; -} - -p,a,ul,li,em,strong,span,div { - font-size: 1em; -} - -p { - width: 37em; -} - -ul, ol { - width: 35em; - margin: 1em 0; -} - -li + li { - margin-top: 1em; -} - -img { - border: 0; -} - -pre { - width: inherit; - overflow-x: auto; -} - -a:link, a:visited, a:active { - color: #1C5380; - padding: 0.1em 0.2ex 0 0.1em; -} - -a:visited { - color: #584781; -} - -a[href]:hover { - color: #111; -} - -a[href^=http] { - background: transparent url(data:image/gif;base64,R0lGODlhCQAJAJEAAP///wAAAP///wAAACH5BAUUAAIALAAAAAAJAAkAAAIXlI8ZK8sdGpggWhrAyXVGSVUGh42OIxQAOw%3D%3D) no-repeat scroll right center; - padding-right: 13px; -} - -a[href$=pdf]:after { - content: ' (pdf)'; -} - - -div.navbar h3, div.navbar h4 { - margin: 0.5em 0; - text-align: center; -} - -ul.menu { - border-right: 1px solid #ddd; - border-left: 1px solid #ddd; - border-top: 1px solid #f0f0f0; - margin: 3em 0; - padding: 0; - list-style-type: none; - width: 100%; -} - -ul.menu li { - padding: 0; - margin: 0.1em 0; -} - -ul.menu li a { - display: block; - padding: 0.2em 1em 0.1em 0.5em; - text-decoration: none; - background: #fafafa; - color: #222; - border-bottom: 1px solid #ddd; - border-top: 1px solid #fefefe; -} - -ul.menu li a:hover { - color: #000; - background: #FEF7ED; - padding: 0.2em 1em 0.1em 0.55em; -} - -ul.menu li a:active { - font-weight: bold; -} - -table { - border: 1px solid #eee; - font-size: 0.8em; -} - -th, td { - border: 0 !important; -} - -th { - font-weight: bold; - font-size: 1em; - border-top: 1px solid #fefefe; - border-bottom: 1px solid #f0f0f0; - background: #FEF7ED; -} - -tr { - background: #fafafa; - color: #222; -} - -tr:hover { - background: #FEF7ED; -} + rmfile ./doc/summary/simplestyle.css hunk ./doc/summary/stmts.html 1 - -
--Statements form the bodies of classes. Within the sequence of statements forming a class definition, there may (and indeed, typically -will) also occur definitions of actions and requests, which themselves have statement sequences as their bodies. -
-Statements will typically have side-effects, affecting the state of objects or the external world. This implies that the order of statements within -a sequence is important. Also, for the statement forms that bind variables, the binding affects only the rest of the sequence. -
-The available statement forms are: -
- svar := expr -
- Here svar is a state variable. These have the same syntax as ordinary variables and share namespace, but - there are no rules for shadowing, so a state variable must be distinct from all ordinary variables in scope (and from other, - already defined state variables in scope). The variable - being defined may not occur in the right hand side. Initialization implicitly declares this variable as part of the state of objects - instantiated from this class. -
These have the same syntax as bind lists in general; they are recursive and within one binding group - order is insignificant (with the - exceptions detailed at the end of the bindings page), but the bindings are only in scope - in the rest of the statement sequence. -
In addition to local bindings as they are used in general, a particularly important case is definitions of actions - and requests (which can only be defined in the statement sequence of a class). -
- var = new expr -
- The expr must evaluate to a class; the effect is that a new object is created, its state initialized and its - interface bound to var -
result expr
- In the sequence of statements of a class, this must be the last statement. It defines the interface of the class, i.e. how - the variable referring to an object may interact with it. -
Within an action or a request, the result statement indicates termination of the method and the value returned (for - requests; for actions the result is (), the dummy value of type ()). -
- The forms of statements up to now are the only forms that may occur in the statement sequence at the outermost level of a class; - creating an object - may only involve initiating the state, creating other objects and returning the proper interface. The remaining forms - occur only within methods and procedures. -
-svar (! expr )*:= expr
-The left hand side is here either a state variable or an array L-value (when the svar is an array). Array indexing -is denoted by the ! operator; several indexing operations may occur for multidimensional arrays. The right hand side may -mention this and other state variables.
-pat <- expr
-Here the right hand side must evaluate to a request or procedure; the statement expresses a call of this method and matching -the pattern against the returned value. -
-The alternative form
-expr -
-may also denote a request or procedure call where the binding is omitted or an action call (which does not return a value). -
-
-after expr expr
-before expr expr
-Here the first expr must be a time interval and the second an action; the latter is given a new baseline (the after case) -or deadline (the before case). -
-if expr then
- stmts
-elsif expr then
- stmts
-else
- stmts
-
-The elsif may occur zero or more times; the else part zero or one time. -
-case expr of
- pat1 -> stmts1
- pat2 -> stmts2
- ...
-
-The alternatives may use guards and/or where clauses just as in function bindings. -
-forall (qual ) + do
- stmts
-
-Here the simplest form of qual is var <- expr, where expr evaluates -to a list. The statement sequence in the body will be executed once for each element of the list, with var bound to -that element. -
-struct Counter where - inc :: Action - read :: Request Int - reset :: Action - -counter = class - s := 0 - inc = action - s := s+1 - read = request - result s - reset = action - s := 0 - result Counter {..} -- rmfile ./doc/summary/stmts.html hunk ./doc/summary/tclass.html 1 - - - -
-In mathematics and in most programming languages, + and - denote addition and subtraction; but what should -their types be? Of course, we want to be able to add both integers and floating-point numbers, but these two functions correspond to -completely different machine operations; we may also want to define arithmetic on new types, such as complex or rational numbers. -
-To better understand the problem, consider a function to add the elements of a list of integers to an accumulator. -Assuming that + only means integer addition we could define -
-add :: Int -> [Int] -> Int -add acc (x : xs) = add (x + acc) xs -add acc [] = acc --
-As long as there are elements in the list, we add them to the accumulator and call the function recursively; when the list is empty the -accumulator holds the result. -
But this function makes perfect sense also for floats (or rationals, or complex numbers, or ...) and we would like to use it at -those types, too. One could imagine an ad hoc solution just for the arithmetic operators, but we prefer a general solution. -
-A first step is to introduce the following struct type: -
-struct Num a where - (+), (-), (*) :: a -> a -> a --
-An object of type Num Int has three fields, defining addition, -subtraction and multiplication, respectively, on integers. (Of course, we can construct an object of this type using any three functions -of the prescribed type, but the intention is to supply the standard arithmetic operators.) Similarly, an object of type Num Float -defines the corresponding operators for floating-point numbers. -
-Assume that we have -properly defined numInt :: Num Int. We can then define -
-add :: Int -> [Int] -> Int -add acc (x : xs) = add (numInt.(+) x acc) xs -add acc [] = acc --
-Unfortunately, the first argument in the recursive call now looks horrible. We cannot accept to write integer addition in this way. But there is -at least something positive; we can generalize the type by giving the Num object as an argument: -
-add :: Num a -> a -> [a] -> a -add d acc (x : xs) = add d (d.(+) x acc) xs -add d acc [] = acc --
-We can now use add for lists of any type of objects for which we can define the arithmetic operators, at the expense of passing an extra -argument to the function. -
-The final step that gives an acceptable solution is to let the compiler handle the Num objects. We do this by declaring -Num to be a type class, loosely following the terminology introduced in Haskell: -
-typeclass Num --
-For such types, the selectors are used without the -dot notation identifying a struct value from which to select. Whenever a selector of a type class occurs in a function -body, the compiler -does the following: -
-Our running example now becomes -
-add :: a -> [a] -> a \\ Num a -add acc (x : xs) = add (x + acc) xs -add acc [] = acc --
-As a convenience, the declaration of the struct type and the type class declaration can be combined into one single declaration: -
-typeclass Num a where - (+), (-), (*) :: a -> a -> a --
-To use function add to sum a list of integers, we could write e.g. add 0 [1, 7, 4]. The compiler must now insert -the extra argument numInt, a struct value with selectors for the three arithmetic operators at type Int. -However, since there might be several objects of type Num Int defined, we must indicate in instance declarations -the objects that are to be used at different types. The definition of the struct value and its instance declaration can be combined -into one declaration. As an example, here is an instance of Num for rational numbers: -
-data Rational = Rat Int Int - -instance numRat :: Num Rational where - Rat a b + Rat c d = Rat (a*d + b*c) (b*d) - Rat a b + Rat c d = Rat (a*d - b*c) (b*d) - Rat a b * Rat c d = Rat (a*c) (b*d) --
-This definition should be improved by reducing the fractions using Euclid's algorithm, but we omit that. We just note that the arithmetic operators in -the right hand sides are at type Int; thus the compiler will insert the proper operations from the instance numInt, avoiding -the overhead of extra parameters. -
-This solution combines ease of use and flexibility with type security. A possible disadvantage is inefficiency; an extra parameter is passed -around. To address this, the user may add a specific type signature; if the user assigns the type Int -> [Int] -> Int to add, -giving up flexibility, the compiler will not add the extra parameter, instead inserting integer operations directly into the function body. -
-Several type classes, including Num, are defined in the Prelude, together with instances for common cases. -
-The compiler must be able to select the proper object of a type class to use whenever a function with a qualified type is used; this choice -is guided by the context of the function application. In certain cases ambiguites can occur; these are resolved using default declarations. -
-Normally, the combined declaration forms are used both for type classes and instances. Separate typeclass declaration of a struct type can only -be done in the module where the struct type is defined. -
-Also subtyping relations may be used as constraints in qualified types. As a simple example, consider the function -
-twice f x = f (f x) --
-Obviously, twice has a polymorphic type. At first, it seems that the type should be (a -> a) -> a -> a. However, it can be assigned -the more general type -
-twice :: (a -> b) -> a -> b \\ b < a --
-Types with subtype constraints will never be assigned by the compiler through type inference, but can be accepted in type-checking. - rmfile ./doc/summary/tclass.html hunk ./doc/summary/timberc.html 1 - -
--This page describes briefly the command line options to timberc, the Timber compiler. -Installation is not described. -
-timberc expects a number of options and a number of files to compile. The most -common uses are the following: -
The given files are compiled (first to C by the timber - compiler, then to object files by the C compiler). No linking takes place. This usage requires that all - files on which the given modules depend have already been compiled. This is the typical way to compile - new modules during the development of a Timber system. Can be modified to option -C to avoid - C compilation. -
The compiler expects Mod.t to be the root module of a system for the default environment (i.e. POSIX). - All modules in the system are compiled by timberc and gcc as needed and in dependency - order, followed by linking. The executable is called Mod. This option obviates the need of a makefile - to rebuild the system after changes in any modules. Can be combined with --root=name when the name of - the root definition is name (rather than the default root). -
Displays the API of module Mod, i.e. all exported kinds, types, defaults and top-level values with their types, - typically in a browser window (installation-dependent). -
- rmfile ./doc/summary/timberc.html hunk ./doc/summary/time.html 1 - -
- --Timber allows explicit expression of time constraints on reactions in -a program. As a basis for this, we assume a notion of absolute or real time, -which progresses independently of program executions. With each action -call in a -program is associated two absolute time instants, the -baseline and the deadline. The intuition is that -execution of the action must not start before the baseline and must -be finished by the deadline. The time interval between these two -instants is the time window of the action. -
-Timber programs cannot express or access absolute time, but the runtime system -has access to a realtime clock and can obtain the current -time.The resolution of this clock is platform-dependent. - -
-There is, instead, a primitive type Time of -durations, or lengths of time intervals, that may occur in -programs. -Time values can also be computed by the runtime system as the -duration of the time interval between two instants. -
-The type is abstract; Time values can be constructed using the -primitive functions -
-sec, millisec, microsec :: Int -> Time --
-which expect a non-negative argument. Of course, e.g., -sec 1 and millisec 1000 denote -the same time value. -
-There is a predefined instance numTime :: Num Time, -so time durations can be added and subtracted using -arithmetic notation, as in sec 2 + millisec 500. -Subtraction of a larger value from a smaller yields -time 0 and multiplication is undefined (an attempt to multiply -two time values raises an exception). -
-To deconstruct time values, one uses the primitive functions -
-secOf, microsecOf :: Time -> Int --
-secOf rounds downwards to whole seconds -and microsecOf returns the fraction, -a value between 0 and 999999. - -
-Time windows of reactions are assigned as follows: -
In particular, the start action of a program gets as - baseline the time instance when program execution begins. -
When a message without time constraints is sent (i.e., an - plain action is called) from a method with current baseline bl and deadline dl, - the reaction to the message inherits both bl and dl.
- The rule in the previous item can be changed by explicit - program constructs: -
The expression after t act - sets the effective baseline for act to the current baseline plus t. -
The expression before t act sets - the effective deadline for act to its effective baseline plus t.
Special case: if the baseline denoted by an after construct is an already passed time instant, - the effective baseline of the reaction is rounded off to the actual time of the call. -
- As mentioned above, programs cannot access absolute time, - but they can measure durations of time intervals. For this, - they make use of the primitive class timer, - where -
-timer :: Class Timer - -struct Timer where - reset :: Request () - sample :: Request Time --
- When a new object of class timer is created, it - stores the baseline of the current reaction. When, later, - sample is called, the duration from the stored time to the - current baseline is returned. Calls to reset updates - the stored time to the current baseline. - -
- Baselines and deadlines provide the basis for scheduling - of Timber programs. The scheduler is preemptive and uses the - EDF strategy (Earliest Deadline First): -
- At each interrupt (from external sources or internal - runtime system timers) or method termination, the reaction to - execute next is chosen as follows: - Messages with future baselines cannot yet execute and are - stored in a list sorted by baseline with a running timer - that expires at the earliest baseline. Eligible messages are - sorted by deadline and the message with the earliest deadline is chosen - for execution. - rmfile ./doc/summary/time.html hunk ./doc/summary/toplevel.html 1 - -
--The body of both the public and private parts of a module is a sequence of -top-level declarations. These declarations comprise -
-Values in Timber are classified into types. The integer value 7 has type Int, a fact that is expressed -in Timber as 7 :: Int, so :: is read "has type". One seldom adds such explicit type information to expressions -in Timber code, but it is allowed to do so. More common is to supply type signatures as documentation to -top-level definitions, but also these can be omitted, leaving to the Timber compiler to infer types. -
-Timber also has type constructors, which can be thought of as functions that take types as arguments and give a type as
-result. An example is the primitive type constructor Request, which takes a type a as an argument and constructs
-the type Request a of methods (in the object-oriented sense) returning a value of type a.
-
-Kinds and kind declarations
-
-Timber types and type constructors are classified by their kind. All types have kind *, while -type constructors that expect one type argument (such as e.g. Request) have -kind * -> *. In general, a kind is either * or k1 -> k2 where k1 and k2 are -kinds. A type constructor of kind k1 -> k2 expects an argument of kind k1; the result is then a type (constructor) -of kind k2. -
-The programmer may declare the kind of a type constructor in a top-level kind declaration:
-con :: kind -
-This is particularly useful when defining abstract data types; in the public part of a module one declares the kind of -an abstract type and the signatures of the operators; the actual type definition and equations are given in the private part. - -
Examples - | Comments | -
---|---|
Stack :: * -> * | Stacks with elements of arbitrary type |
Dictionary :: * -> * -> * | Dictionaries storing info about keys |
-We first describe the primitive types of Timber. In Timber code it is always clear from the context whether -an expression denotes a type or a value, so some types use the same syntax for type expressions as for -values, without confusion. (A beginner might disagree about the last two words.) - -
-As part of the language, the following primitive types are provided: -
-Literals of types Int and Float are as in most programming languages; integer constants can be -given in octal or hexadecimal formed if prefixed by 0o and 0x, respectively. -
-Time values are expressed using the primitive functions sec, millisec, microsec and nanosec, -which all take an integer argument and return a Time value. Of course, millisec 1000 and sec 1 denote -the same value. -
-Character literals are written within -single quoutes as in 'a' or '3'; common escaped characters are '\n' and '\t' for newline and tab, respectively. (Many other forms of -character literals omitted.) -
-The following type constructors are also primitive in the language. -
The type [a], for any type a, contains finite lists of values of type a. - The list [3, 6, 7, 1] has type [Int] and [[3, 2], [4, -1, 7]] has type [[Int]] - (however, see the overloading page for more general types of these lists). -
-For arbitrary types a1,a2,...an, we can form the tuple type (a1, a2, ..., an). -Values use the same notation so (True,'a') has type (Bool,Char). -
-For any type a, the type Array a consists of a sequence of a values, organized so that one can access all values -by index in constant time. Arrays are particularly useful as state variables in objects, where they may also be -updated in imperative style.
For any two types a and b, a -> b is the type of functions from a to b. --> associates to the right, so a -> b -> c parses as a -> (b -> c). -
-This type could be defined in Timber as -
-data Either a b = Left a | Right b --
-It is only primitive because of its role in generating default instances.
-For any type a, the type Class a contains templates from which one can instantiate objects -with interface of type a. Of particular -interest is the case where a is a struct type with a number of methods manipulating an internal state of the object.
-Action is the type of asynhronous methods. An object may offer an Action in its interface; a client who has access to this interface -may send the object an action message with appropriate arguments. The message will, at an unspecified later point in time, execute the action, with -exclusive access to the object's state.
-For any type a, Request a is the type of synchronous methods that return a value of type a. An object -may offer a Request in its interface; a client who has access to this interface may then send a request message with appropriate -arguments and wait for the result. Since all methods require exclusive access to the state of the receiving object during execution, cycles of requests lead to deadlock. Deadlock is detected by the runtime system and an exception is raised.
For any two types s and a, Cmd s a is the type of procedures that can execute in a -state s and return a value of type a. -
-For any type a, Ref a is the type of references to -objects with interface of type a. -
-We can now form complex types such as - -
Examples - |
---|
Int -> Int -> Bool |
[Int] -> Int |
(a -> Bool) -> [a] -> [a] |
-The two first examples are monomorphic; they involve only known types and type constructors. The third is polymorphic; -it involves the type variable a (a type variable since it starts with a lower-case letter), that stands for an -arbitrary type. A function possessing this type can be used at any type obtained by substituting a type for a. -
-The type variable a is implicitly bound in such a type expression; one should think of an implicit "for all a"
-quantification prepended to the type expression.
-Data types
-
-The programmer may introduce new ways of constructing data by defining data types. The simplest case is enumeration types like -
-data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun --The type Day contains the seven constructor values that are enumerated in the right hand side. -
-The constructors may have arguments, as in -
-data Temp = Fahrenheit Int | Celsius Int --
-Values in type Temp are e.g., Fahrenheit 451 and Celsius 100. There may be one, two or more alternatives -and a constructor may have more than one argument. A data type for a web log entry might be -
-data Entry = Entry IPAddress Date URL Method Int --
-where a value of type Entry might be -
-Entry "123.456.789.000" (May 29 2007) "http://www.abc.def" GET 321 --
-given suitable type definitions for the other types involved. Note that the type and the constructor have the same name; this is -OK since types and constructors live in different namespaces. -
-We may also define parameterised data types: -
-data Tree a b = Nil | Branch (Tree a b) a b (Tree a b) --
-Tree thus has kind * -> * -> * and a value of type Tree String Int is a binary tree with a String and an Int stored in each internal node. -
-Two different data types may not use the same constructor name; with the above definition, no other data type in the same module can -use constructor Nil. For data types in imported modules there is no problem if they use Nil; only that the -qualified name must be used for the imported constructor. - -
-Struct, or record, types collect values bound to named selectors. Declarations have the syntax -
-struct con var * where
- sig+
-
- -
Examples - |
---|
struct Point where |
x, y :: Int |
struct Dictionary a b where |
insert :: a -> b -> Action |
lookup :: a -> Request (Maybe b) |
-An example value of type Point is Point {x=3, y=7}. The order between the fields is not significant, so -Point {y=7, x=3} is the same value. Similarly as for constructors, two different struct types in the -same module may not use the same selector name. -Thus a struct value is uniquely defined by the collection of selectors and the type name can be omitted from the value; {x=3, y=7} is again the same value. -
-If p :: Point, the selectors are accessed using dot notation, so the two integer coordinates are -p.x and p.y, respectively. -
-A struct type may have any number of selectors and the types of selectors are arbitrary. A struct type may also be parameterised -as shown by Dictionary, a type suitable as an interface to an object that acts as a dictionary, storing information of type b about keys -of type a. (The result type Maybe b for lookup is intended to capture the possibility that the given -key is not stored in the dictionary; the prelude defines data Maybe a = Nothing | Just a.) - -
-The user may introduce new names for existing types: -
-type Age = Int -type IPAddress = String -type List a = [a] -type Pair a b = (a,b) --
-Such definitions do not introduce new types; they can only be helpful to improve program readability. They may not be recursive and -can not be partially applied (i.e., Pair Int is not a legal type constructor). The prelude introduces one type synonym: -
-type String = [Char] --
-Struct types and data types may be defined in subtype hierarchies. As an example, we can extend Point: -
-struct Point3 < Point where - z :: Int --
-We define Point3 to be a subtype of Point; for struct types this means that Point3 has all the selectors -of Point and possibly some more (in the example, one more: z). So we have {x=0, y=3, z=5} :: Point3. -A function that expects a Point as argument can be given a Point3 without problem, since all the function can do -with its argument is use the selectors x and y, which are present also in a Point3. -
-As another example we might split the dictionary type into two: -
-struct LookupDict a b where - lookup :: a -> Request (Maybe b) - -struct Dictionary a b < LookupDict a b where - insert :: a -> b -> Action --
-In a program we may build a dictionary dict :: Dictionary a b and then send it to an unprivileged client typed as a -LookupDict; the client can then only lookup information, not insert new key/info pairs. -
-A struct type may have several supertypes; given a struct type -
-struct Object where - self :: OID --where OID is a type that allows test for equality between objects, we could have defined -
-struct Dictionary a b < LookupDict a b, Object where - insert :: a -> b -> Action --
-to get the same effect as before and, in addition, the possibility to test whether two dictionaries are the same (meaning same object, -not equivalent content). -
-We can also define hierarchies of data types, but these are completely separate from any hierarchy of struct types; a data type -can never be a sub- or supertype of a struct type. For data types we may add new constructors to get a supertype: -
-data CEntry > Entry = Corrupt --
-Type CEntry adds another constructor to the type Entry defined above; a CEntry is either a proper -entry as above or Corrupt. A function that is defined to take a Entry as argument cannot accept a CEntry; -it may stumble on a Corrupt entry. The converse is OK; newly defined functions on CEntry values can happily -take an Entry; they will not have to use their Corrupt case. - -
-The following subtyping relations hold between primitive types:
-Class a < Cmd s a
-Request a < Cmd s a
-Action < Cmd s Msg
-Ref a < OID.
-
rmfile ./doc/summary/types.html
rmdir ./doc/summary
rmdir ./doc
hunk ./examples/Counter_descr.html 1
-
-
-The Counter example is a minimal example of a class from which one -can instantiate objects with state. Several variations are possible; -here is the one we choose: -
-module Counter where - -struct Counter where - incr :: Action - decr :: Action - value :: Request Int - -counter = class - - n := 0 - - incr = action n := n+1 - - decr = action n := n-1 - - value = request result n - - result Counter{..}-
-Comments: -
-ctr = new counter --The variable ctr has type Counter, and the newly - created object can be updated by method calls ctr.incr and - ctr.decr. The state can be read by -
-val <- ctr.value --
-counter = class - - n := 0 - - result - struct - incr = action n := n+1 - decr = action n := n-1 - value = request result n --In more complex situations, the {..} is a useful convenience. -
-counterInit init = class - - n := init - - ... --The rest of the class is as before. To create an object with initial -value 5, we would write -
-ctr = new counterInit 5 --
-Thus, we have the typing counterInit :: Int -> Class Counter. -
-We might still keep the definition of counter, but this would -mean code duplication that should be avoided. Instead, we could write -
-counter = counterInit 0 --and get a class counter with the same usage as our original -definition. - rmfile ./examples/Counter_descr.html hunk ./examples/Echo2_descr.html 1 - - - -
-Let us make the Echo program just a little bit more -interesting: We add an initial welcome phrase and a -prompt with a line number. Here is the program: -
-module Echo2 where - -import POSIX - -root env = class - - count := 1 - - prompt = do - env.stdout.write (show count++"> ") - count := count+1 - - echo str = action - env.stdout.write str - prompt - - result - action - env.stdin.installR echo - env.stdout.write "Welcome to Echo2!\n" - prompt --
-The root definition now has two more components: -
-In addition, the callback and the initial action both call -prompt, and a greeting phrase is added. -
-Some additional details: -
The keyword do signifies the start of a, - typically local, procedure, that may be called from other methods - as above.
show is a function that converts - the integer value count to a string; ++ - denotes string concatenation. Both these are defined in - the Prelude, a library module which is implicitly imported by - all modules.
The user input string given to echo will include - the newline; hence so will the string echoed to stdout. - But to write the welcome phrase on a separate line, it will have - to end with an explicit newline.
-Now, let's try a variation; program Echo3 writes -Hello!\n to stdout once a second. The user can change this -message by typing a line on stdin; after the line is finished -with a return, the line typed will be the new message. Here is the program: -
-module Echo3 where - -import POSIX - -root env = class - - current := "Hello!\n" - - save str = action - current := str - - tick = action - env.stdout.write current - after (sec 1) tick - - result - action - env.stdin.installR save - tick --
The scheduled execution time (the baseline) for each instance of tick is - one second after the baseline of the previous instance. Thus there - is no ackumulating drift in the program, even if a particular tick may be delayed in - execution. -
-When running Echo3 one notices a peculiarity of the standard -implementation of the POSIX environment: the screen doubles - as both the output -device stdout and as user feedback part of the input device -stdin. Thus, output is intertwined with input characters in a -rather unsatisfactory way. - rmfile ./examples/Echo3_descr.html hunk ./examples/EchoServer2_descr.html 1 - -
- --This is a minor extension of EchoServer: when started, it -expects an integer command line argument maxClients, denoting -the maximal number of concurrently served clients. If more clients -connect, they are just informed that the server is busy and -disconnected. -
-module EchoServer2 where - -import POSIX -import Counter - -port = Port 12345 - -root env = class - - clients = new counter - - log str = action - env.stdout.write ('[':str ++ "]\n") - - result action - maxClients = parse (env.argv ! 1) - env.inet.tcp.listen port (server maxClients clients log) - -server maxClients clients log sock = class - - n := 1 - - p = show sock.remoteHost - - echo str = action - sock.outFile.write (show n ++"> "++str) - n := n+1 - - close = request - clients.decr - log (p ++ " closing") - result () - - neterror str = log ("Neterror: "++str) - - established = action - cl <- clients.value - if cl < maxClients then - clients.incr - log ("Connected from " ++ p) - sock.inFile.installR echo - else - sock.outFile.write "Server busy" - log ("Refused " ++ p) - sock.close - - result Connection{..} --
- We need to keep track of the number of served clients. - For this we use a Counter - object, created by the root object. -
When a new client connects, the counter value is retrieved and - only if this value is small enough is an echo action installed; - otherwise the client is informed that the server is busy and the - socket closed. When a client closes the connection, the counter is decreased. -
- A Counter object is appropriate here, since several server objects, - each interacting with one client, interacts with it. On the - contrary, the line number local to each server object is maintained - in a simple integer state variable. - - rmfile ./examples/EchoServer2_descr.html hunk ./examples/EchoServer_descr.html 1 - -
- --Now, let's look at a further feature of the POSIX -environment. It also supports writing network programs, -that communicate over the Internet using sockets. -A socket can be thought of as a two-way communication channel, -consisting of both an RFile and a WFile. -
-Two network programs, which -execute on different machines, may connect over -the network and communicate using a socket. -Typically, one of the programs will be a server -and the other a client. Here is a trivial server, the -EchoServer. - This server waits indefinitely for clients to connect on port - 12345. When a client connects, the server starts a session, where - client input rows are echoed back to the client, prefixed by a line - number. Several clients may be served concurrently and - line numbering is independent for each client. - -
-module EchoServer where - -import POSIX - -port = Port 12345 - -root env = class - - log str = action - env.stdout.write ('[':str ++ "]\n") - - result action - env.inet.tcp.listen port (server log) - - -server log sock = class - - n := 1 - - p = show sock.remoteHost - - echo str = action - sock.outFile.write (show n ++"> "++str) - n := n+1 - - close = log (p ++ " closing") - - neterror str = log ("Neterror: "++str) - - established = action - log ("Connected from " ++ p) - sock.inFile.installR echo - - result Connection{..} --
-Comments to the code: -
-In order to let you run the server, we provide a simple client, -TCPClient. We do not list the code here; you may review -it in TCPClient.t. The client accepts a host name and a port -number as command line arguments and connects to a server on that -address. When connection is established, the client accepts user input -lines, sends them to the server and displays replies obtained on the -screen. - rmfile ./examples/EchoServer_descr.html hunk ./examples/Echo_descr.html 1 - -
- --Our first example runs in a very simple setting: a computing environment -where the interaction between the external world and the program is through a keyboard and a text screen. -The user provides input using the keyboard and the program prints -output on the screen. -
-We consider a reactive program, where the user -input is just echoed on the screen, line by line, -by the program. This trivial interaction, the "Hello, world" of -reactive programs, goes on indefinitely. -
-Here is the program: -
-module Echo where - -import POSIX - -root env = class - - echo str = action - env.stdout.write str - - result - action - env.stdin.installR echo --
-Let us explain the program: -
-Module POSIX defines a struct type Env, with selectors -corresponding to the resources available to the program in its interaction -with the environment. -Among these are stdin, which refers to the keyboard, -and stdout, which refers to the screen.
-root :: Env -> Class Action --
- -In module Echo, this definition starts on line 5 and -makes up the rest of the program. -
-root must describe the initial behaviour of the program in its -result action, which terminates the class definition. -
-In addition, it may make auxiliary definitions; here of -the function echo, which describes how the program -reacts to an input string str. -The resulting action just installs this function as -a callback with env.stdin. -
When executed, the runtime system invokes the -result action of the root definition (see -Echo2 for a more careful description.) -After that, the program is idle, waiting for user input. -When such (line-buffered) input occurs, the runtime system -invokes the callback with the input line as argument. -
-This trivial program is typical for the Timber programming idiom; -we describe how the program should react to external events and -install, or register, this description with the external device. -
-We note, finally, that the use of stdout and -stdin is consistent with their types as -specified in Env: -
-examples> ./MasterMind -Welcome to Mastermind! -Choose your secret. Press return when ready. - -My guess: Red Blue Blue Red -Answer (two integers): 1 1 -My guess: Blue Black Yellow Red -Answer (two integers): 2 0 -My guess: Green Black Red Red -Answer (two integers): 0 0 -My guess: Blue Blue Yellow White -Answer (two integers): 3 0 -My guess: Blue Blue Yellow Blue -Answer (two integers): 3 0 -My guess: Blue Blue Yellow Yellow -Answer (two integers): 4 0 -Yippee! -Do you want to play again? (y/n) n -examples> --The program is too long to display here. We only note a few things: -
-examples> ./MasterMind -Welcome to Mastermind! -Choose your secret. Press return when ready. - -My guess: Red Blue Blue Red -Answer (two integers): 1 1 -My guess: Blue Black Yellow Red -Answer (two integers): 2 0 -My guess: Green Black Red Red -Answer (two integers): 0 0 -My guess: Blue Blue Yellow White -Answer (two integers): 3 0 -My guess: Blue Blue Yellow Blue -Answer (two integers): 3 0 -My guess: Blue Blue Yellow Yellow -Answer (two integers): 4 0 -Yippee! -Do you want to play again? (y/n) n -examples> --The program is too long to display here. We only note a few things: -
+ result action + primes!0 := 2 + count := 1 + forall k <- [3..limit] do + p <- isPrime k + if p then + count := count + 1 + primes!count := k + env.stdout.write (show (count+1)++"\n") + env.exit 0 ++The choice has negligible effect on efficiency (the tail recursive +checkFrom is transformed to iteration by the compiler), +but is merely a matter of taste. +
We end by noting two mathematical facts that the program relies +on: +
+procedure checkFrom. +
+all elements are initialised to the value of the second argument). +
-As a reactive program, this is quite degenerate: when started, it -expects -a positive integer n>2 as command line argument. It -computes all primes smaller than or equal to n, prints -the number of such primes to stdout and terminates. -
-The algorithm used illustrates imperative programming using updatable -arrays in Timber. Here is the program: -
-module Primes where - -import POSIX - -root env = class - limit :: Int - limit = parse (env.argv!1) - primesBound = limit `div` log3 limit - - primes := uniarray primesBound 0 - count := 0 - - isPrime k = loop 0 - where loop n = do - p = primes!n - if p*p > k then - result True - elsif k `mod` p == 0 then - result False - else loop (n+1) - - checkFrom k = do - p <- isPrime k - if p then - primes!count := k - count := count + 1 - if k < limit then checkFrom (k+1) - - result action - primes!0 := 2 - count := 1 - checkFrom 3 - env.stdout.write (show count++"\n") - env.exit 0 - - -log3 :: Int -> Int -log3 n - | n < 3 = 0 - | otherwise = 1 + log3 (n `div` 3) - --
-The root action notes that 2 is a prime and initiates count -to 1; it then checks numbers for primeness, starting with 3 in -procedure checkFrom. The iterative check is expressed using -recursion, checking for successive numbers up to limit. -
-The procedure isPrime works by trial division, using already -discovered primes: to check whether k is a prime, one tries -to find a proper prime factor p such that p*p <= k. If -none is found, k is prime. - - - ) ) ) ) merger 0.0 ( merger 0.0 ( merger 0.0 ( hunk ./examples/Primes_descr.html 72 -procedure checkFrom. The iterative check is expressed using -recursion, checking for successive numbers up to limit. -
+procedure checkFrom. +
+all elements are initialised to the value of the second argument). +
-As a reactive program, this is quite degenerate: when started, it -expects -a positive integer n>2 as command line argument. It -computes all primes smaller than or equal to n, prints -the number of such primes to stdout and terminates. -
-The algorithm used illustrates imperative programming using updatable -arrays in Timber. Here is the program: -
-module Primes where - -import POSIX - -root env = class - limit :: Int - limit = parse (env.argv!1) - primesBound = limit `div` log3 limit - - primes := uniarray primesBound 0 - count := 0 - - isPrime k = loop 0 - where loop n = do - p = primes!n - if p*p > k then - result True - elsif k `mod` p == 0 then - result False - else loop (n+1) - - checkFrom k = do - p <- isPrime k - if p then - primes!count := k - count := count + 1 - if k < limit then checkFrom (k+1) - - result action - primes!0 := 2 - count := 1 - checkFrom 3 - env.stdout.write (show count++"\n") - env.exit 0 - - -log3 :: Int -> Int -log3 n - | n < 3 = 0 - | otherwise = 1 + log3 (n `div` 3) - --
-The root action notes that 2 is a prime and initiates count -to 1; it then checks numbers for primeness, starting with 3 in -procedure checkFrom. The iterative check is expressed using -recursion, checking for successive numbers up to limit. -
-The procedure isPrime works by trial division, using already -discovered primes: to check whether k is a prime, one tries -to find a proper prime factor p such that p*p <= k. If -none is found, k is prime. - - - ) ) ) hunk ./examples/Primes_descr.html 77 -none is found, k is prime. - +none is found, k is prime. +
+ result action + primes!0 := 2 + count := 1 + forall k <- [3..limit] do + p <- isPrime k + if p then + count := count + 1 + primes!count := k + env.stdout.write (show (count+1)++"\n") + env.exit 0 ++The choice has negligible effect on efficiency (the tail recursive +checkFrom is transformed to iteration by the compiler), +but is merely a matter of taste. +
We end by noting two mathematical facts that the program relies +on: +
+all elements are initialised to the value of the second argument). +
-As a reactive program, this is quite degenerate: when started, it -expects -a positive integer n>2 as command line argument. It -computes all primes smaller than or equal to n, prints -the number of such primes to stdout and terminates. -
-The algorithm used illustrates imperative programming using updatable -arrays in Timber. Here is the program: -
-module Primes where - -import POSIX - -root env = class - limit :: Int - limit = parse (env.argv!1) - primesBound = limit `div` log3 limit - - primes := uniarray primesBound 0 - count := 0 - - isPrime k = loop 0 - where loop n = do - p = primes!n - if p*p > k then - result True - elsif k `mod` p == 0 then - result False - else loop (n+1) - - checkFrom k = do - p <- isPrime k - if p then - primes!count := k - count := count + 1 - if k < limit then checkFrom (k+1) - - result action - primes!0 := 2 - count := 1 - checkFrom 3 - env.stdout.write (show count++"\n") - env.exit 0 - - -log3 :: Int -> Int -log3 n - | n < 3 = 0 - | otherwise = 1 + log3 (n `div` 3) - --
-The root action notes that 2 is a prime and initiates count -to 1; it then checks numbers for primeness, starting with 3 in -procedure checkFrom. The iterative check is expressed using -recursion, checking for successive numbers up to limit. -
-The procedure isPrime works by trial division, using already -discovered primes: to check whether k is a prime, one tries -to find a proper prime factor p such that p*p <= k. If -none is found, k is prime. - - - ) ) hunk ./examples/Primes_descr.html 72 -procedure checkFrom. The iterative check is expressed using -recursion, checking for successive numbers up to limit. -
+procedure checkFrom. +
-As a reactive program, this is quite degenerate: when started, it -expects -a positive integer n>2 as command line argument. It -computes all primes smaller than or equal to n, prints -the number of such primes to stdout and terminates. -
-The algorithm used illustrates imperative programming using updatable -arrays in Timber. Here is the program: -
-module Primes where - -import POSIX - -root env = class - limit :: Int - limit = parse (env.argv!1) - primesBound = limit `div` log3 limit - - primes := uniarray primesBound 0 - count := 0 - - isPrime k = loop 0 - where loop n = do - p = primes!n - if p*p > k then - result True - elsif k `mod` p == 0 then - result False - else loop (n+1) - - checkFrom k = do - p <- isPrime k - if p then - primes!count := k - count := count + 1 - if k < limit then checkFrom (k+1) - - result action - primes!0 := 2 - count := 1 - checkFrom 3 - env.stdout.write (show count++"\n") - env.exit 0 - - -log3 :: Int -> Int -log3 n - | n < 3 = 0 - | otherwise = 1 + log3 (n `div` 3) - --
-The root action notes that 2 is a prime and initiates count -to 1; it then checks numbers for primeness, starting with 3 in -procedure checkFrom. The iterative check is expressed using -recursion, checking for successive numbers up to limit. -
-The procedure isPrime works by trial division, using already -discovered primes: to check whether k is a prime, one tries -to find a proper prime factor p such that p*p <= k. If -none is found, k is prime. - - - ) hunk ./examples/Primes_descr.html 68 -all elements are initialised to the value of the second argument -The program uses the moderately clever bound that the number -of primes up to n is at most n `div` log3 n. -
+all elements are initialised to the value of the second argument). +
-As a reactive program, this is quite degenerate: when started, it -expects -a positive integer n>2 as command line argument. It -computes all primes smaller than or equal to n, prints -the number of such primes to stdout and terminates. -
-The algorithm used illustrates imperative programming using updatable -arrays in Timber. Here is the program: -
-module Primes where - -import POSIX - -root env = class - limit :: Int - limit = parse (env.argv!1) - primesBound = limit `div` log3 limit - - primes := uniarray primesBound 0 - count := 0 - - isPrime k = loop 0 - where loop n = do - p = primes!n - if p*p > k then - result True - elsif k `mod` p == 0 then - result False - else loop (n+1) - - checkFrom k = do - p <- isPrime k - if p then - primes!count := k - count := count + 1 - if k < limit then checkFrom (k+1) - - result action - primes!0 := 2 - count := 1 - checkFrom 3 - env.stdout.write (show count++"\n") - env.exit 0 - - -log3 :: Int -> Int -log3 n - | n < 3 = 0 - | otherwise = 1 + log3 (n `div` 3) - --
-The root action notes that 2 is a prime and initiates count -to 1; it then checks numbers for primeness, starting with 3 in -procedure checkFrom. The iterative check is expressed using -recursion, checking for successive numbers up to limit. -
-The procedure isPrime works by trial division, using already -discovered primes: to check whether k is a prime, one tries -to find a proper prime factor p such that p*p <= k. If -none is found, k is prime. - - - hunk ./examples/Primes_descr.html 63 +
-Reflex is a simple reaction time tester. -Only the Return key is used in interaction with -the program. When pressing Return for the first time, -the user is instructed to Wait...; after a few seconds, -the program says Go! and the user must -strike Return again as fast as possible. The elapsed -time is displayed and the test can be repeated. -
-Here is the program: -
-module Reflex where - -import POSIX - -data State = Idle | Holding Msg | Counting - -root env = class - - print str = env.stdout.write (str ++ "\n") - - tmr = new timer - - state := Idle - - enter _ = action - case state of - Idle -> msg <- after (sec 2) action - tmr.reset - print "Go!" - state := Counting - print "Wait..." - state := Waiting msg - - Holding msg -> abort msg - print "Cheat!!!" - state := Idle - - Counting -> t <- tmr.sample - print (format t) - state := Idle - - result - action - env.stdin.installR enter - print "Press return to start" - -format t = show (secOf t) ++ '.' : fracs ++ " secs" - where t100 = microsecOf t `div` 10000 - fracs = if t100<10 then '0':show t100 else show t100 --
-Comments to the code: -