summaryrefslogtreecommitdiff
path: root/ml
diff options
context:
space:
mode:
authormichele.simionato <devnull@localhost>2007-12-02 14:12:36 +0000
committermichele.simionato <devnull@localhost>2007-12-02 14:12:36 +0000
commitb672466c102677799fcaf10cc98580c5537735c1 (patch)
tree8bce07517ba93f759280fa008bab45a15474ac18 /ml
parent07279fd0cb5e642a4068ffa808f381d01674eccf (diff)
downloadmicheles-b672466c102677799fcaf10cc98580c5537735c1.tar.gz
Added my article on SML to the repository
Diffstat (limited to 'ml')
-rw-r--r--ml/article1.txt362
-rw-r--r--ml/article2.txt324
-rw-r--r--ml/article3.txt347
-rw-r--r--ml/article4.txt453
-rw-r--r--ml/article5.txt44
5 files changed, 1530 insertions, 0 deletions
diff --git a/ml/article1.txt b/ml/article1.txt
new file mode 100644
index 0000000..5b28c23
--- /dev/null
+++ b/ml/article1.txt
@@ -0,0 +1,362 @@
+Functional Programming For Dynamic Programmers - Part 1
+=======================================================
+
+:author: Michele Simionato
+:date: December 2007
+
+This is the first of a series of articles on functional programming in
+statically typed languages. It is intended for dynamic programmers, i.e.
+for programmers with a background in dynamically typed languages, such as Perl,
+Python, Ruby, or languages in the Lisp family. The approch is eminently practical
+and example-based; the main goal is to see if we can stole some good idea from
+statically typed languages. In order to be concrete, I will consider languages
+in the ML family, because they are pretty nice and much easier to understand
+that Haskell.
+
+Declaration of intents
+----------------------
+
+One may rightly wonder why to study functional languages, in a
+particular statically-typed ones [#]: after all, their relevance in
+enterprise programming is negligible, they are unknown for system
+administration task, and unless you are a computer science researcher
+you have no need to know them. All that is true; on the other hand, if
+you believed it, you would not be a dynamic programmer, you would have
+stick with C and you would not be a reader of my papers.
+dynamic programmer is the kind of person who, when everbody says
+";the Earth is flat", will wonder: "is the Earth *really* flat?". So,
+even if everybody says that object orientation is good and that
+inheritance is the best thing after sliced bread, a dynamic programmer
+will be suspicious of these claims and will seek for alternatives.
+Exactly in the same way he escaped from the enslaving by static typing
+in old fashioned languages, he will escape from the enslaving by
+dynamic typing languages, if he finds valid alternatives. A dynamic
+programmer has a kind of Casanova complex, and he will never be loyal
+to a single language.
+In particular, a dynamic programmer will judge academic languages
+worth of investigation: he may decided not to use them, but still he may get
+some good ideas from them. After all, Python stole the list comprehension
+idea from Haskell and iterators from Icon; Ruby stole many ideas from Scheme
+and Smalltalk; Perl stole from everybody.
+I always wanted to learn a modern statically-typed functional
+language, at least to have something intelligent to say in the endless
+usenet discussions on dynamic typing vs. static typing; recently, by
+accident, I run into Standard ML (SML, ML stands for Meta Language)
+and I found out it has a very clean syntax, so I decided to learn it
+[#].
+SML is practically unknown outside academia (its cousins Caml and F# are a
+little more known, but they are certainly very far away from being
+mainstream languages) and I am not interested in advocating it for use
+in enterprise programming; after all in enterprise programming the technical
+advantages of a language count very little compared to thing like the support
+you can get, the ability to find skilled programmers, the interoperability with
+your existent codebase and development environment (I mean the tools and
+libraries you use, the database, etc). My motivation here is to learn something
+from SML, and to try to avoid mistakes in mainstream languages which have
+been already fixed in SML. Let me give a concrete example: in the past I have been
+using Zope and Twisted, which are enterprise-level Python frameworks. They
+share a common implementation of interfaces. I have always had a bad gut
+feeling about Zope interfaces: I always thought they were overkill, complex, and
+not doing by default what they (In my opinion) should do, i.e. interface checking.
+I always thought there should be a better solution (Python 3.0 actually will
+have a simple implementation of interfaces in the core language)
+but until I studied SML I had no idea of how the solution should look like.
+I think SML has the better module system I have ever seen; and my goal
+here is to popularize it, trying to get some of SML ideas in Python frameworks.
+
+Micro-introduction to functional languages
+------------------------------------------------------------
+
+Simply put, functional languages are programming languages that try very hard to
+avoid mutation and side effects. There are no pure functional
+languages in use, since an absolutely pure language would have to rule
+out input and output and it would be pretty much useless;
+nevertheless, some functional languages are purer that others. For
+instance, there are languages which have some support for functional
+programming, but are not considered functional (i.e. Python); others,
+like Lisp, which is regarded as the grandfather of functional
+languages, that are pretty much regarded as impure nowadays; Scheme is
+somewhat perceived as more functional than Common Lisp, but this is
+debatable, and in any case it is not very pure; Standard ML (SML) is
+often perceived as purer than Scheme, but mostly because of
+syntactical convenience, not of technical merit; Haskell is possibly
+the purest functional language commonly used, but still can be used in
+an imperative way. This classification is sloppy and wrong in more
+than one way; nevertheless it is useful (in my personal opinion) in
+the sense that it gives and indication of how much the language
+departs from a mainstream imperative language, and how difficult it is
+to learn it. Functional languages come in two kinds: dynamically
+typed (Lisp, Scheme, Erlang ...) and statically typed (SML, Haskell
+...). Programmers used to dynamic typing (i.e Pythonistas, Rubystas,
+etc) will have less trouble to understand dynamically typed functional
+language, so it is more interesting (in my opinion) to look at
+statically typed languages. After all, I think a programmer should have at
+least a statically typed language in his toolbox (C++ and Java do not
+count). SML is the simplest statically language out there, so l decided to
+start with it
+
+SML is a language with many implementations, so if you want to try it,
+you must decide which implementation to use. I have played with some
+of them, including SML of New Jersey (http://www.smlnj.org) and MLton
+(http://mlton.org) but at the end I have decided to use Alice ML,
+since it has a lot of innovative features, an interesting set of libraries, and
+some clean syntax extensions. It is also a very dynamic version of SML,
+so that dynamic programmers will not feel too constrained ;-)
+On Ubuntu, you can install it with
+``apt-get install alice-runtime`` (having added
+``deb http://www.ps.uni-sb.de/alice/download/debian stable contrib`` to your
+``/etc/apt/sources.list``) where on the Mac, you can download the
+``.dmg`` installer and add ``/Applications/Alice.app/Contents/Resources/bin``
+to your PATH. There is also an installer for Windows, but if you are a dynamic
+programmer I do not expect you to use Windows, unless you are forced
+to ;)
+
+Having installed Alice you can start the "interpreter" or REPL
+(read-eval-print-loop) [#]_ as follows::
+
+ $ alice
+ Alice 1.4 ("Kraftwerk 'Equaliser' Album") mastered 2007/04/24
+ ### loaded signature from x-alice:/lib/system/Print
+ ### loaded signature from x-alice:/lib/tools/Inspector
+ ### loaded signature from x-alice:/lib/distribution/Remote
+
+Now you can write your first mandatory "Hello world" program::
+
+ - print "Hello world\n";
+ Hello world
+ val it : unit = ()
+
+and you are ready to start ;) If you are an old timer Emacs user, you
+may also want to install (Aqua)Emacs and the sml-mode for Emacs (Alice
+has a custom version of it, that you can download from here_ ).
+
+.. _here: http://www.ps.uni-sb.de/alice/download/sml-mode-4.0+alice.zip
+
+.. [#] Modern statically-typed language here means a language with
+ type-inference, such as SML and Haskell. We all know that
+ there are no good ideas to be extracted from ancient
+ statically typed languages such as Java, C and C++ ;)
+
+.. [#] In principle, one may argue that choosing a language because of
+ its syntax is stupid and that one should look at its features,
+ libraries, reliability, etc; in practice, many languages are
+ more or less equivalent in terms of features, libraries and
+ reliability, so that the main factor for the choice of the
+ language is it syntax. Also, when you are a beginner and you
+ need to write only simple programs, syntax is all that
+ matters.
+
+.. [#] Technically the Alice REPL is not an interpreter: the
+ expressions you enter are compiled on the fly and executed
+ immediately, not interpreted. However, the overall
+ user-experience is the same as if you had an
+ interpreter. This approach is commons in ML and Lisp implementations.
+
+"Hello world", Part I
+---------------------------------------
+
+In the previous section I have shown how the traditional "Hello world"
+program looks in ML. ML is a language without statements (as usual in
+functional languages; statements are actually a bad idea IMO, even
+for imperative languages [#]_) so *print* is a function taking a string in
+input and returning an empty tuple in output, as you
+can see from the last line of output
+
+``val it: unit = ()``
+
+The empty tuple is of type ``unit`` and it is the sole representative of that
+type (i.e. it is a singleton). In general, any object has a type;
+for instance, if you enter the number 42 at the prompt you will get
+
+::
+
+ - 42;
+ val it: int = 42
+
+The REPL just prints a string representation of the value
+you entered, together with its type (in this case, int).
+
+A point to notice in the "Hello world" program
+is the lack of parenthesis: we wrote ``print
+"Hello world\n";`` and not ``print("Hello world\n")``. This is
+possible since the ``print`` function in ML takes only a *single*
+argument; actually *all* functions in SML takes a single argument!
+
+You may wonder how is it possible to program anything serious if all
+functions take a single argument: the answer is that the single
+argument can be of a composite type, for instance a tuple. So you may
+define functions like the following
+
+::
+
+ - fun print2 (arg1, arg2)= (print arg1; print arg2);
+ val print2 : string * string -> unit = _fn
+
+Here ``print2`` takes a single argument, which is a 2-tuple (a pair),
+and returns the null (unit) value. The interesting thing is that the
+compiler has been able to figure out by itself that the arguments must
+be of string type, since ``print`` expects a string, and that
+``print2`` will return an ``unit`` value, since ``print`` does so: we
+are seeing here the type -inferencer at work. We also see that a
+function is just a value as any other value, i.e. functions are first
+class objects, as usual in dynamics languages; its type is
+``string * string -> unit``.
+
+Let us check that ``print2`` works as expected::
+
+ - print2 ("hello ", "world");
+ hello world
+ val it: unit = ()
+
+If you want to print a generic number of arguments, you can use a list::
+
+ - fun printList lst = app print lst;
+ val printList : string list -> unit =_fn
+ - printList["Hello ", "World", "!", "\n"];
+ Hello World!
+ val it : unit = ()
+
+The builtin function ``app`` apply the ``print`` function to each element of the
+list from left to right.
+
+ML does not have default arguments, so you cannot write the analogous
+of this Python function::
+
+ >>> def printUser(user="Michele"):
+ ... print "Hello,", user
+ >>> printUser()
+ Hello, Michele
+ >>> printUser("Mario")
+ Hello, Mario
+
+In Python, ``printUser`` can be called with zero or one arguments, but in ML this
+is not possible, since functions with different arity are of a different type and
+ML does not support function overloading; however, you can however work around
+this feature [#]_ by using options. ML has a standard *option* type, used for
+objects which may have a NONE value; any object can be converted into an option
+by wrapping it with SOME. An example will make it clear. Let me define::
+
+ - fun printUser(userOpt: string option) =
+ printList ["Hello, ", getOpt(userOpt, "Michele"), "\n"];
+ val printUser : string option -> unit = _fn
+
+where *getOpt(opt, default)* is a builtin function which returns the
+value of the option, or the default if the option have value NONE. We
+may call *printUser* as follows::
+
+ - printUser NONE;
+ Hello, Michele
+ - printUser (SOME "Mario");
+ Hello, Mario
+
+The syntax is definitively ugly, and there are actually clever tricks
+to implement default arguments in a nicer way, but they are too
+advanced for this introduction. But stay tuned for the next issues ;)
+
+.. [#] Incidentally, in current Python ``print`` is a statement and it
+ does not return anything, but in Python 3000 ``print`` will be
+ function returning None
+
+.. [#] The lack of function overloading may be seen as a feature or as
+ a limitation, depending on the reader.
+
+Functional programming and Input/Output
+-----------------------------------------------------
+
+Input/output is the black ship of functional programming and it is
+often relegated at the end of tutorials and sometimes even omitted, as
+if shameful. Sometime, it is not even standardized and
+implementation-dependent. On the other hand, *all* programs must
+perform some kind of input/output, or at least of output, otherwise we
+would have no way to see what a program did. Therefore input/output
+*must* be explained at the beginning of any tutorial, not at the
+end. I always hated books not telling me how to read a file until the
+appendix! In this section I will explain how you can read a file in
+SML. Reading a file is for some reason seen as "inpure" since it is
+not functional. Let me explain that a bit more: in mathematics, a
+function takes an argument in input, and returns an output; if I call
+twice the function with the same argument, I get twice the *same*
+output. In programming, a procedure reading a line from a file returns
+a *different* line at each invocation, even if called with the same
+arguments (the arguments maybe simply the empty tuple), so it is not a
+function in the mathematical sense. On the other hand, a procedure
+writing a line into a file, is also impure, since it is modifying an
+object, the file itself.
+In strict functional programming there is no
+mutation, objects are declared once and for all times they do not
+change. Functional programming in its purest form is therefore useless:
+notice that even the paradigmatic "Hello world" program is not a functional
+program, since the "Hello world" string is printed via an imperative side
+effect. In other words, every functional programming language must find a
+non-functional way to manage input-output. Haskell tries very hard to hide
+non-functional constructs into monads; SML just uses traditional
+imperative constructs to perform input/output. We already saw the
+``print`` function to write on stdout; to read from stdin, you can
+define the following utility::
+
+ - fun input prompt = (print prompt; getOpt(TextIO.inputLine TextIO.stdIn, ""))
+ val input : string -> string = _fn
+
+The parenthesis here are needed since the right hand side of a function definition
+must be an expression, and the parenthesis (plus the expression separator ";")
+allows you to compose expressions in a single expression returning as value
+the value of the last expression. ``TextIO`` is a module in the standard library
+managing textual I/O and ``TextIO.inputLine inputFile`` is a function
+returning a line wrapped into an option object or NONE if we arrived at the
+end of the input file. In particular, in the case of standard input,
+we arrive at the end when we give CTRL-D (in a Unix-like system); in
+this case ``input`` will return the empty string, otherwise it returns the
+input line, comprehensive of the newline character.
+
+Here is an example of usage::
+
+ - input "Enter a string: ";
+ Enter a string: hello
+ val it : string = "hello\n"
+ - input "Enter CTRL-D ";
+ - Enter CTRL-D
+ val it : string = ""
+
+I we want to read a text file (assuming it fits in memory)
+the simplest way is to use ``TextIO.inputAll``::
+
+ - fun fileToString filename = let
+ val file = TextIO.openIn filename
+ in
+ TextIO.inputAll file finally TextIO.closeIn file
+ end
+
+Conversely, if we want to write a text on a file we can define::
+
+ - fun saveFile (fname, content) = let
+ val out = TextIO.openOut fname
+ in
+ TextIO.output(out, content) finally TextIO.closeOut out
+ end;
+
+The examples here use the standard *let* expression, which has the form::
+
+ let
+ <bindings>
+ in
+ <expression; .. ; expression>
+ end
+
+and returns as value the value of the last expression. Moreover, the examples
+here use the *finally* construct, which is an Alice extension to SML, and
+works as you would expect::
+
+ <expression possibly raising exceptions> finally <cleanup expression>
+
+the finally clause if executed always, even
+if there is an exception in the first expression.
+
+The examples here are very simple and do not address the issue or reading
+or writing large files which do not fit in memory. But don't worry,
+we will address those situations in the next issues, have faith!
+
+----
+
+*A long journey starts with the first step*
+
+ -- old Chinese saying
diff --git a/ml/article2.txt b/ml/article2.txt
new file mode 100644
index 0000000..400b364
--- /dev/null
+++ b/ml/article2.txt
@@ -0,0 +1,324 @@
+Functional Programming For Dynamic Programmers - Part 2
+=======================================================
+
+:author: Michele Simionato
+:date: 10 November 2007
+
+This is the second of a series of articles on functional programming in
+statically typed languages. It is intended for dynamic programmers, i.e.
+for programmers with a background in dynamically typed languages, such as Perl,
+Python, Ruby, or languages in the Lisp family. The approch is eminently practical
+and example-based; the main goal is to see if we can stole some good idea from
+statically typed languages. In order to be concrete, I will consider languages
+in the ML family, because they are pretty nice and much easier to understand
+that Haskell.
+
+Loops
+----------------------------------------------------
+
+Perhaps the most common construct in imperative programming is the *for* loop;
+in spite of that, *for* loops are usually missing in functional languages. In this
+section I will explain and the way to work around this omission.
+To start with a practical example, suppose we want to define a function
+to count the number of lines in a text file, something akin to the following
+Python code [#]_::
+
+ def countLines(fname):
+ counter = 0
+ with file(fname) as f:
+ for line in f:
+ counter += 1
+ return counter
+
+.. [#] We are using here the ``with`` statement, available in Python 2.5 by
+ importing it from the future: ``from __future__ import with_statement``.
+
+How can we implement it without a *for* loop?
+One solution is to cheat and to use a *while* loop, which exists in SML::
+
+ fun countLines fname = let
+ val counter = ref 0
+ val inp = TextIO.openIn fname
+ in
+ while not (TextIO.endOfStream inp) do
+ (TextIO.inputLine inp; counter := !counter + 1)
+ finally TextIO.closeIn inp;
+ !counter
+ end
+
+Some explanation about ML references is in order here.
+ML does not allow to mutate a variable directly (as a matter of fact
+most types in ML are immutable); if you want to increment an integer,
+you must wrap it into a reference object, and you must mutate the
+reference. Some simple experiment at the prompt should give you
+the gist of what references are.
+
+Put the integer 0 into a memory location and returns a reference to it::
+
+ - val counter = ref 0;
+ val counter : int ref = ref 0
+
+Return the value in the location pointed by the reference::
+
+ - !counter;
+ val it : int = 0
+
+Put in that location the value 0+1; return the empty tuple::
+
+ - counter := !counter + 1;
+ val it : unit = ()
+
+Return the new value of the counter::
+
+ - !counter
+ val it : int = 1
+
+From this explanation, it should be obvious what ``countLines`` does;
+the implementation works, but it is very ugly and strongly discouraged. I
+show it here, to prove that SML can be used in an imperative way, not
+to suggest to code in this way. However, it may be
+not obvious to re-implement ``countLines`` without mutation, unless
+you have already coded in functional languages.
+
+There is a standard tecnique to solve this kind of problem, i.e. the conversion of an
+imperative loop into a functional recursion: *the accumulator tecnique*.
+
+The accumulator is the mutating parameter in the imperative loop, in this case, the
+counter. The accumulator tecnique consists in rewriting the loop
+as a recursive function, promoting the accumulator to the rank of additional
+parameter in the function signature::
+
+ - fun countLines' (file, counter) =
+ case TextIO.inputLine file
+ of NONE => counter
+ | SOME line => countLines'(file, counter + 1);
+ val countLines' : TextIO.instream * int -> int = _fn
+
+As you see, ``countLines'`` is a recursive function calling itself
+with an incremented counter, until the file is read completely, then
+it returns the final value of the accumulator. You can then rewrite the
+original function as
+
+::
+
+ - fun countLines (fname) = let
+ val file = TextIO.openIn fname
+ in
+ countLines' (file, 0)
+ finally TextIO.closeIn file
+ end;
+ val countLines : string -> int = _fn
+
+Recursion and accumulators are ubiquitous in functional programming, so the
+time spent understanding this example is worth it. I will close this paragraph
+by noting that the accumulator tecnique is also used to convert non-tail-call
+recursive functions like the good old factorial::
+
+ - fun fact 0 = 1
+ | fact n = n*fact (n-1);
+
+into a tail-call recursive function, i.e. a function returning either a value without
+making a recursive call, or directly the result of a recursive call::
+
+ - fun fact n = fact' (n, 1)
+ and fact' (0, acc) = acc
+ | fact' (n, acc) = fact' (n-1, acc*n);
+
+Here I have use the ``and`` syntax to define two or more conceptually connected
+functions in a single step.
+
+Tail-call recursive functions are equivalent to imperative loops, in this case to
+the Python code::
+
+ def fact(n):
+ acc = 1
+ while n > 0:
+ acc = acc*n
+ n = n-1
+ return acc
+
+Internally, the compiler of functional languages are able to translate tail-call
+recursive functions back to imperative loops, so that the implementation is
+very efficient. In a language like Python instead, which is not a truly functional
+language, it is possible to write::
+
+ def fact(n, acc):
+ if n == 0:
+ return acc
+ else:
+ return fact(n-1, acc*n)
+
+but this function is not converted into a loop, you will have a loss of performance
+and you will incur in the recursion limit if try to compute the factorial of a
+large enough integer (say 1000) [#]_ .
+
+.. [#] Notice that Python does not make tail call optimization *on
+ purpose*, essentially for two reasons: 1) the language has a
+ philosophy of preferring iteration over recursion; 2) keeping the
+ recursive calls in the stack gives more informative tracebacks and
+ helps debugging. Since I am at that, let me notice that Python error
+ reporting and debugging features are infinitely superior to the ones
+ of any SML or Scheme implementation I have seen. This is not because
+ of lack of tail call optimization, it is because as a general
+ philosophy Python does not care about speed but cares about
+ programmer; moreover, despite the fact that SML
+ and Scheme are twice as old as Python, a lot more of work went into
+ Python than in SML/Scheme for what concerns practical issues.
+
+Higher order functions
+---------------------------------------------------------
+
+Just as recursion is pervasive in functional programming, so are
+higher order functions. You may judge how much functional is a language
+by measuring how good is the support for recursion and for higher order
+functions. In this respect, ML shines since it has a particularly elegant syntax to
+define higher order functions i.e. functions returning functions.
+
+.. higher order functions: http://en.wikipedia.org/wiki/Higher_order_functions
+
+The canonical example of higher order function is the adder::
+
+ - fun adder n = fn x => x+n;
+ val adder : int -> int -> int = _fn
+
+The notation ``fn x => x+n`` denotes what is usually called a lambda
+function, according to the Lisp tradition; in this example it means
+that the ``adder`` returns a function which adds *n* to any integer
+number; for instance::
+
+ - val add1 = adder 1; (* adds 1 to any number *)
+ val add1 : int -> int = _fn
+ - add1 1;
+ val it : int = 2
+
+Notice that ML use the notation ``int -> int -> int`` to denote the type of
+the adder, which should be read as
+
+ ``int -> (int -> int)``
+
+i.e. *the arrow associates on the right* and should be interpreted as
+"the adder is a function taking an *int* and returning a function *int->int*".
+On the other hand, *function application associates on the left* and
+`` adder 1 2`` should be read as
+
+ ``(adder 1) 2``
+
+An equivalent, but cleaner notation for the adder is
+
+::
+
+ - fun adder n x = x+n;
+ val adder : int -> int -> int = _fn
+
+Notice the difference betwen ``adder(n, x)``, denoting a function of
+two arguments, and ``adder n x`` denoting an higher order function,
+so that ``adder n`` is a function itself.
+
+The ``adder`` is a simple example,
+but it does not make justice to the usefulness of higher order functions.
+To give a practical example, we may consider the problem of avoiding
+the boilerplate when opening/closing a file. Lisp use for that a few
+macros (``with-input-from-file``, ``with-output-to-file``) whereas
+Python use a special syntax (the ``with`` statement); in ML it is quite
+natural to define a higher order function such as the following::
+
+ - fun ` manage fname = let
+ val file = TextIO.openIn fname
+ in
+ manage file
+ finally TextIO.closeIn file
+ end;
+ val ` : (TextIO.instream -> 'a) -> string -> 'a = _fn
+
+Here ````` is just an identifier for the higher order function; I could have used
+for it a longer name, such as
+``higherOrderFunctionAddingAutomaticOpenCloseFunctionality``, but I am lazy,
+and also I wanted to show that in ML one has a considerable freedom in the choice
+of valid identifiers. The action of ````` is clear: it takes a function which operates
+on TextIO.stream objects (i.e. text files) and converts it into a function that
+operates on strings (i.e. file names) and has opening/closing functionality
+embedded. The type of the return value is not specified at this stage, and
+this is indicated by the notation *'a* (to be read alpha), which denotes a
+generic type.
+Using ````` the ``fileToString`` function defined in the first
+article of this series could be written as simply as::
+
+ - val fileToString = `TextIO.inputAll;
+ val fileToString : string -> string = _fn
+
+whereas ``countLines`` could be written as::
+
+ - val countLines = `(fn file => countLines'(file, 0))
+ val countLines : string -> int = _fn
+
+You should begin to appreciate the power of higher order functions, now ;)
+An evident weakness of the approach used here, is that it works only
+for text files (actually only for files opened for input; we would need to
+define a different higher order function for files opened for output);
+if we wanted to wrap binary files, we would need
+to define an equivalent higher order function using the ``BinIO`` library
+instead of ``TextIO``; then, if we wanted to use it for sockets, we would need
+to define yet another higher order function; in general there
+are infinite resources which can be opened and closed, and we could define
+an infinite number of higher order functions doing all the same thing.
+This is bad; fortunately this potentially infinite code duplication can be solved
+using functors, but you will have to wait for the next articles to see how to do it ;)
+
+Higher order functions can also be used to implement poor man's object
+systems; consider for instance this example::
+
+ class Counter(object):
+ def __init__(self, initial_value):
+ self.initial_value = self.value = 0
+ def incr(self):
+ self.value += 1
+ def show(self):
+ print "The value is %d" % self.value
+ def reset(self):
+ self.value = self.initial_value
+
+We can get the same effect via a stateful higher order function (a.k.a. a closure)::
+
+ exception MissingMethod
+
+ fun makeCounter initialValue = let
+ val value = ref initialValue
+ in
+ fn "reset" => value := initialValue
+ | "show" => (print The value is "; print (Int.toString (!value)); print "\n")
+ | "incr" => value := !value + 1
+ | _ => raise MissingMethod
+ end
+
+ val counter = makeCounter 0;
+
+ do counter "incr";
+ do counter "show"; (* The value is 1 *)
+ do counter "reset";
+ do counter "show"; (* The value is 0 *)
+
+This example also shows the usage of pattern matching and of exceptions.
+
+You can rewrite it in a functional way as follows:
+
+----
+
+*The venerable master Qc Na was walking with his student, Anton. Hoping to
+prompt the master into a discussion, Anton said "Master, I have heard that
+objects are a very good thing - is this true?" Qc Na looked pityingly at
+his student and replied, "Foolish pupil - objects are merely a poor man's
+closures."*
+
+*Chastised, Anton took his leave from his master and returned to his cell,
+intent on studying closures. He carefully read the entire "Lambda: The
+Ultimate..." series of papers and its cousins, and implemented a small
+Scheme interpreter with a closure-based object system. He learned much, and
+looked forward to informing his master of his progress.*
+
+*On his next walk with Qc Na, Anton attempted to impress his master by
+saying "Master, I have diligently studied the matter, and now understand
+that objects are truly a poor man's closures." Qc Na responded by hitting
+Anton with his stick, saying "When will you learn? Closures are a poor man's
+object." At that moment, Anton became enlightened.*
+
+ -- Anton van Straaten
diff --git a/ml/article3.txt b/ml/article3.txt
new file mode 100644
index 0000000..3991f89
--- /dev/null
+++ b/ml/article3.txt
@@ -0,0 +1,347 @@
+Functional Programming For Dynamic Programmers - Part 3
+=======================================================
+
+:author: Michele Simionato
+:date: November 2007
+
+This is the third of a series of articles on functional programming in
+statically typed languages. It is intended for dynamic programmers, i.e.
+for programmers with a background in dynamically typed languages, such as Perl,
+Python, Ruby, or languages in the Lisp family. The approch is eminently practical
+and example-based; the main goal is to see if we can stole some good idea from
+statically typed languages. In order to be concrete, I will consider languages
+in the ML family, because they are pretty nice and much easier to understand
+that Haskell.
+
+Structures, modules, packages, components and all that
+------------------------------------------------------
+
+Usually programs start small, but they have an unfortunate tendency to
+grow, getting larger and larger and eventually to explode. To control
+this tendency, programmers have invented various techniques, which are
+essentially all variations of a same idea: large programs should be
+decomposed in smaller, more manageable, conceptually connected units
+of code. These units of code go under various names, depending on the
+language you are using; common terms are structures, classes,
+namespaces, modules, packages, libraries, components etc. In this
+article I will focus on the ML terminology and tecniques.
+
+In SML, the basic mechanism of code control is the structure, which
+takes the place of what is called a module in other languages. We
+already encountered structures before, such as the ``TextIO``
+structure, containing functions such as ``TextIO.openIn``,
+``TextIO.closeIn`` etc.
+
+It is also possible to define custom structures. For instance, suppose
+we want to implement Python-like file-iteration in SML in order to be
+able to write things like ``Iter.app print (Iter.file fname)`` to
+print all the lines in a text file. We can do so with the following
+structure::
+
+ - structure Iter = struct
+
+ exception StopIteration
+
+ fun app func iter =
+ (while true do func (iter ())) handle StopIteration => ()
+
+ fun map func iter =
+ fn () => func (iter ())
+
+ fun file fname = let
+ val inp = TextIO.openIn fname
+ in fn () =>
+ (case TextIO.inputLine inp
+ of NONE => raise StopIteration
+ | SOME line => line)
+ handle err => (TextIO.closeIn inp; raise err)
+ end
+ end;
+ structure Iter :
+ sig
+ exception StopIteration
+ val app : ('a -> 'b) -> (unit -> 'a) -> unit
+ val map : ('a -> 'b) -> (unit -> 'a) -> unit -> 'b
+ val file : string -> unit -> string
+ end
+
+We see many interesting things here. First of all, the REPL returns us
+a string representation of the so-called *signature* of the structure,
+i.e. a description of the types of the objects encapsulated by the
+structure. Iterators have been implemented as thunks, i.e. functions
+of type ``unit -> 'a``; in particular, ``file`` is a higher order
+function taking a filename and returning a string-value thunk: at each
+call of the closure``Iter.file fname`` we get a different line of the
+file. All types have been inferred correctly: ``Iter.app`` is an
+higher order function taking a generic function ``'a->'b`` (which
+means a function taking an unspecified type ``'a`` and returning an
+unspecified type ``'b``, possibly different from ``'a``) and
+converting it into a function ``iterator -> unit``, whereas
+``Iter.map`` applies a generic function to an iterator and returns an
+iterator. For instance, suppose we want to define an utility to
+convert to upper case a text file, by applying the function [#]_
+
+ ``- fun upper str = String.implode (map Char.toUpper (String.explode str));``
+
+to each line; we can test it by writing a file like the following::
+
+ $ cat three-lines.txt
+ line 1
+ line 2
+ line 3
+
+and by defining
+
+::
+
+ - val next = Iter.map upper (Iter.file "three-lines.txt");
+ val next : unit -> string = _fn
+
+With this definitions, we get the same behavior as in Python [#]_ ::
+
+ - next ();
+ val it : string = " LINE 1\n"
+ - next ();
+ val it : string = " LINE 2\n"
+ - next ();
+ val it : string = " LINE 3\n"
+ - next ();
+ Uncaught exception
+ StopIteration
+
+.. [#] In this example I am using the ``String`` and ``Char`` structures of the
+ SML standard library, documented here
+ http://www.standardml.org/Basis/string.html and here
+ http://www.standardml.org/Basis/char.html
+
+.. [#] In Python we would write
+
+::
+
+ >>> it = itertools.imap(str.upper, file("three-lines.txt"))
+ >>> it.next()
+ ' LINE 1\n'
+ >>> it.next()
+ ' LINE 2\n'
+ >>> it.next()
+ ' LINE 3\n'
+ >>> it.next()
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ StopIteration
+
+Structures in the standard library are automatically available; on the other
+hand, if you write your own structure and save it into a file, you need to
+import the file before you can use it. The simplest way to import a file is
+through the ``use`` expression::
+
+ - use "<filename.aml>";
+
+This simply includes the imported file in the current program, and everything
+is compiled together. In most SML implementation it is also possible to compile
+a file as a standalone component; the details vary with the implementation.
+In Alice you can just save the above structure into a file called ``iter.aml``
+and compile it as
+
+ ``alicec iter.aml``
+
+This creates a bytecode compiled file called ``iter.alc``.
+The compiled structure can be imported in your programs with the line
+
+ ``import structure Iter from "iter"``
+
+assuming ``iter.alc`` is in the same directory as your main program.
+If you want to import in the program namespace all the objects defined
+inside the structure, you can open it:
+
+ ``- open Iter;``
+
+this is however actively discourages, to prevent namespace pollution, i.e.
+name conflicts, since an exported name can shadow a pre-existent name.
+There is actually only a good use case for opening a structure, i.e. inside
+another structure. In particular, it is possible to redefine structures, augmenting
+them with additional objects as in this example::
+
+ - structure Iter = struct
+ open Iter
+ fun binfile (fname, chunksize) = let
+ val inp = BinIO.openIn fname
+ in
+ fn () => let
+ val vec = BinIO.inputN (inp, chunksize)
+ in
+ if Word8Vector.length(vec) = 0 then raise StopIteration else vec
+ handle err => (BinIO.closeIn inp; raise err)
+ end
+ end
+ end;
+
+Here I have redefined the ``Iter`` structure by adding a routine to read
+binary files in chunks. Notice that ``BinIO.inputN`` returns a vector
+of bytes, not a string; however, you can get a *bona fide* string by
+applying the standard library function Byte.bytesToString_ to
+the returned chunks. Here is an example::
+
+ - Byte.bytesToString (Iter.binfile("three-lines.txt", 40) ());
+ val it : string = " line 1\n line 2\n line 3\n"
+
+An importanting to notice is that *you can redefine even standard library
+structures*, augmenting them with new features, or replacing objects
+with others, even *with a different signature*. This is similar to what
+happens in Ruby, where you can add methods even to builtin classes,
+and should be done with care.
+
+.. _Byte.bytesToString: http://www.standardml.org/Basis/byte.html
+
+Structures are not first class values
+-----------------------------------------------------------
+
+The problem with structures is that they are not first class values, so they cannot
+be passed to functions and they cannot be inspected. This is the reason why giving at
+the prompt the name of a structure does not work::
+
+ - TextIO;
+ 1.0-1.6: unknown value or constructor `TextIO'
+
+``TextIO`` is not recognized as the name of a know value. Structures live
+in a completely separate namespace, so that you can associate any value
+to the name ``TextIO`` [#]_
+
+::
+
+ - val TextIO = "astring";
+ val TextIO : string = "astring"
+
+and still you can access the contents of the structure without any problem::
+
+ - TextIO.print;
+ val it : string -> unit = _lazy
+
+Structures can be given name and aliases via the ``structure`` declaration;
+for instance, if you want to give a shorter alias to TextIO you can define
+
+ ``- structure T=TextIO;``
+
+Structures can be arbitrarily nested, i.e they can contain
+substructures at any level of nesting. For instance, if you want to
+extract the substructure ``StreamIO`` from ``TextIO`` you can define
+
+ ``- structure S=TextIO.StreamIO;``
+
+The lack of first class structures is motivated by reasons of (premature) optimization.
+Suppose structure where first class values: then you could write things like
+
+ ``val S = if someRuntimeCondition() then struct ... end else struct ... end``
+
+and that would make life pretty hard for the compiler: basically, it would be
+impossible to compile the structure once and for all, and you would be forced
+to recompile it at runtime. In these days of just-in-time
+compilation this is less of an issue than in the past, and in particular
+Alice ML allows you to do that, by wrapping structures in packages.
+But in order to discuss that, we must first discuss signatures, which is
+the SML name for interfaces.
+
+Signatures as a form of restricted import
+--------------------------------------------
+
+Signatures are another kind of non-first-class objects.
+Every structure has a principal signature, which is the most specific signature
+for that structure. In practice, the principal signature
+the one shown by the prompt if you do no specify a custom signature;
+however, it is possible to define more
+generic versions of the principal signature. To be concrete, let me
+consider two structures of the standard library,``TextIO`` and ``BinIO``;
+their principal signatures are different since they have different implementations,
+but still they share many
+features and it is possibile to define subsignature(s) matching both.
+For instance, you could define a simplified interface for IO as follows::
+
+ signature SIMPLE_IO = sig
+ type instream
+ type outstream
+ type vector
+ val openIn: string-> instream
+ val closeIn: instream -> unit
+ val openOut: string-> outstream
+ val closeOut: outstream -> unit
+ val inputAll: instream -> vector
+ val output: outstream * vector -> unit
+ end;
+
+and you could import only a subset of the features provided by ``TextIO``
+and ``BinIO`` as follows::
+
+ structure T = TextIO:SIMPLE_IO;
+ structure T :
+ sig
+ type vector = vector
+ type instream = TextIO.instream
+ type outstream = TextIO.outstream
+ val openIn : string -> TextIO.instream
+ val inputAll : TextIO.instream -> vector
+ val closeIn : TextIO.instream -> unit
+ val openOut : string -> TextIO.outstream
+ val output : TextIO.outstream * vector -> unit
+ val closeOut : TextIO.outstream -> unit
+ end = TextIO
+
+
+ structure B = BinIO:SIMPLE_IO;
+ structure B :
+ sig
+ type vector = vector
+ type instream = BinIO.instream
+ type outstream = BinIO.outstream
+ val inputAll : BinIO.instream -> vector
+ val closeIn : BinIO.instream -> unit
+ val output : BinIO.outstream * vector -> unit
+ val closeOut : BinIO.outstream -> unit
+ val openIn : string -> BinIO.instream
+ val openOut : string -> BinIO.outstream
+ end = BinIO
+
+ - open BinIO:SIMPLE_IO;
+ - val f = B.openIn "three-lines.txt";
+ val f : BinIO.instream = _val
+ - val x = Byte.bytesToString (B.inputAll f);
+ - B.closeIn f;
+
+.. [#] You will get a warning about violating standard naming conventions, since
+ a regular value such as a string should be denoted with a non-capitalized
+ identitifier, whereas capitalized identitifiers should be reserved to structures.
+
+Opaque signatures and information hiding
+----------------------------------------------------
+
+The rationale behind opaque signatures
+is that they make easier to replace an implementation
+with another without breaking the interface.
+
+(which are a way of implementing the
+facade pattern)
+http://en.wikipedia.org/wiki/Facade_pattern
+
+Another advantage of signatures is that they allow to implement information
+hiding
+
+http://en.wikipedia.org/wiki/Information_hiding
+
+i.e. if your structure contains private methods which are not meant to be
+exposed to the application programmer you can just provide a signature not exporting
+them. On the other hand, the application program has still the choice to ignore
+your proposed signature and use the principal signature: in this case of course,
+he will take his risks, since the interface of private methods is not guaranteed
+and could change in future versions of the library, but he can do that if he
+needs it.
+
+::
+
+ - structure T=TextIO:>SIMPLE_IO;
+ structure T : SIMPLE_IO
+
+
+----
+
+ *divide et impera*
+
+ -- old Roman saying
diff --git a/ml/article4.txt b/ml/article4.txt
new file mode 100644
index 0000000..6c42a18
--- /dev/null
+++ b/ml/article4.txt
@@ -0,0 +1,453 @@
+Functional Programming For Dynamic Programmers - Part 4
+=======================================================
+
+:author: Michele Simionato
+:date: November 2007
+
+This is the fourth of a series of articles on functional programming in
+statically typed languages. It is intended for dynamic programmers, i.e.
+for programmers with a background in dynamically typed languages, such as Perl,
+Python, Ruby, or languages in the Lisp family. The approch is eminently practical
+and example-based; the main goal is to see if we can stole some good idea from
+statically typed languages. In order to be concrete, I will consider languages
+in the ML family, because they are pretty nice and much easier to understand
+that Haskell.
+
+Functors
+------------------------------------------------------
+
+As we saw in the previous article, structures are not first class objects and
+they cannot be passed to and returned from regular functions.
+To circumvent this restriction, the authors of ML invented
+the concept of *functor*, which is basically a *sui generis* function
+taking structures in input and to returning structures in output. Functors
+are not-first-class objects themselves and therefore they require a specific
+declaration, such as the following::
+
+- functor Wrap(SimpleIO:SIMPLE_IO) = struct
+ val inputAll = SimpleIO.inputAll
+ output = SimpleIO.output
+ fun fileIn manage fname = let
+ val file = openIn fname
+ in
+ manage file finally closeIn file
+ end
+ fun fileOut manage fname = let
+ val file = openOut fname
+ in
+ manage file finally closeOut file
+ end
+ end
+
+The functor here is important, since it shows how it is possible to write
+generic code in SML. In this case, I have just written a library which is
+able to wrap *any* structure matching the ``SimpleIO`` interface, and I have
+avoided a potentially infinite code duplication.
+The specification of which specific structure to use will be the job of the client
+code, not of the library author; in particular a particular user of the library
+may be interested in specializing it both for ``TextIO`` and ``BinIO``
+by writing:
+
+- structure T = Wrap(TextIO)
+- structure B = Wrap(BinIO)
+
+The operation of specializing a functor is also called *functor instantiation*;
+since it happens in a structure declaration it is performed by the compiler
+*at compile time*. The advantage is that the compiler can generate different optimized
+code for the structures``T`` and ``B`` in the *client* program.
+
+do print (IO.fileIn IO.inputAll "three-lines.txt")
+
+The Standard ML type system
+-------------------------------------------------------------------
+
+We have already seen many builtin types, such integers, strings, lists, etc.
+The type system of SML is extensible, and the user can define new types in terms
+of primitive types.
+
+In SML any value has a type, but types itself are not values, i.e. they are
+not first class values. That means that passing the name of a type to the
+prompt gives an error::
+
+ - string;
+ 1.0-1.6: unknown value or constructor `string'
+
+Just as structures, types live in a separated namespace. The lack of
+first class types also means the lack of metaclasses which are common
+in dynamic languages such as Smalltalk, Lisp, Perl, Python, Ruby,
+etc. Besides, SML types are not classes in any OO sense of the term,
+you cannot introspect them, there are no methods, and no inheritance;
+so, the first step in order to learn the SML type system is to forget
+everything you know about OOP ;) Having said that, you can certainly
+program in an OO style in ML, using closures as we saw in our previous
+essay, or using functors as we will show in the next paragraph; the
+point here is that you don't use types for OOP, types are used
+for pattern matching.
+
+Pattern matching in turn (among many other things) can be used to implement
+runtime type dispatching. For instance, suppose, you want to define an utility
+function casting integer to strings. The first thing to do is to define an
+int_or_string datatype with two constructors INT and STR:
+
+- datatype int_or_string = INT of int | STR of string;
+
+
+Now it is possible to implement the casting function via pattern
+matching on the constructors
+
+ - fun valueToString (INT x) = Int.toString x
+ | valueToString (STR x) = x;
+ val valueToString : int_or_string -> string = _fn
+
+Let me check that it works:
+
+ - valueToString (INT 1);
+ val it : string = "1"
+ - valueToString (STR "1");
+ val it : string = "1"
+
+With this trick it is possible to emulate C++-style function overloading.
+
+In particular he may define composite types, like the following::
+
+ - datatype string_int = STRING_INT of string * int;
+ datatype string_int = STRING_INT of string * int
+ -
+
+The uppercase identifier is called the constructors of the datatype, and can
+be used to make concrete instances of the type::
+
+ - STRING_INT("hello", 1);
+ val it : string_int = STRING_INT ("hello", 1)
+ -
+
+Notice is that the type itself is not a first class value::
+
+ - string_int;
+ 1.0-1.10: unknown value or constructor `string_int'
+ +
+
+where the constructor is a first class value, being simply a function::
+
+ - STRING_INT;
+ val it : string * int -> string_int = _fn
+
+It is also possible to define polymorphic types, where the constructor can
+accept any type as argument. For instance, suppose we want to define a generic
+container type::
+
+ - datatype 'a container = CONTAINER of 'a;
+ datatype 'a container = CONTAINER of 'a
+ -
+
+#- CONTAINER
+
+
+
+a *named_function* type corresponding
+to a pair *(function, name)*, where *function* can be of any functions, whereas
+*name* is a string.
+We can do it as follows::
+
+ - datatype ('a, 'b) named_function = NAMED_FUNCTION of ('a->'b) * string;
+ datatype ('a, 'b) named_function = NAMED_FUNCTION of ('a -> 'b) * string
+ -
+
+*named_function* is a parametric type with parameter 'a (to be read *alpha*),
+which corresponds to a generic type, and NAMED_FUNCTION is its associated
+constructor::
+
+ - NAMED_FUNCTION;
+ val it : ('a -> 'b) * string -> ('a, 'b) named_function = _fn
+ -
+
+In other words, NAMED_FUNCTION is a function converting a pair (value, name),
+where *value* can be of any type, into a *named_function* parametric type.
+Here is an example::
+
+ - NAMED_FUNCTION (fn x=>2*x, "double");
+ (* giving a name to the function x=>2*x *)
+ val it = NAMED_FUNCTION (fn,"double") : (int,int) named_function
+ -
+
+Finally, let me notice that SML also allows to define enumeration
+types, like the following one::
+
+ - datatype color = RED|GREEN|BLUE;
+ datatype color = BLUE | GREEN | RED
+ -
+
+but for
+enumeration types the name is rather improper, since they are just values::
+
+ - RED;
+ val it : color = RED
+ -
+
+..
+
+ - GREEN;
+ val it : color = GREEN
+ -
+..
+
+ - BLUE;
+ val it : color = BLUE
+ -
+
+Polymorphism
+-------------------
+
+ - functor Sequence(ListOrVector:) = funct
+ end
+
+
+Two examples of simple structures in the standard library as List and Vector;
+they act as modules with a mostly compatible interface, providing functions
+to manipulate lists and vectors respectively. Since SML is a functional language,
+both lists and vectors are immutable. Here are a few examples of usage::
+
+ - val lst = [0,1,2];
+ val lst : int list = [0, 1, 2]
+ - val vec = #[0,1,2];
+ val vec : int vector = #[0, 1, 2]
+
+ - List.length(lst);
+ val it : int = 3
+ - Vector.length(vec);
+ val it : int = 3
+
+ -List.sub(lst, 1) (*) take the second element of the list
+ val it : int = 1
+ -Vector.sub(vec, 1) (*) take the second element of the vector
+ val it : int = 1
+
+signature HAS_LENGTH = sig
+ val length:
+functor(F:HAS_LENGTH):
+
+polyLength(List)
+
+
+Lists
+---------------------------------------------------
+
+Lists are the most common data structures in functional languages (they formed
+the core of Lisp at its beginning) and there are many facilities to manage them and
+to iterate over them. For instance, in the first article of this series, I showed the
+``app`` builtin, to apply a function over the elements of a list; there is also
+a ``map`` builtin to build a new list from an old one::
+
+ - val doubles = map (fn x => 2*x) [1,2,3];
+ val doubles : int list = [2, 4, 6]
+
+and a ``filter`` function to extract the sublist of elements satisfying a given predicate::
+
+ - fun isEven n = n mod 2 = 0;
+ - val even = List.filter isEven [1,2,3];
+ val even : int list = [2]
+
+Moreover, you can append lists with the ``@`` operator::
+
+ - [1] @ [2] @ [3,4];
+ val it : int list = [1, 2, 3, 4]
+
+There are other standard facilities and you can look at the documentation
+http://www.standardml.org/Basis/list.html to find them all.
+
+ML lists are linked lists in the same sense of Lisp or Scheme [#]_, however they
+are immutable. Just as in Scheme [#]_, where
+
+ ``(list 1 2)``
+
+is a shortcut for
+
+ ``(cons 1 (cons 2 '()))``
+
+in ML
+
+ ``[1, 2]``
+
+is a shortcut for
+
+ ``1::2::[]``
+
+and ``::`` is the *cons* operator (short for constructor).
+
+
+.. [#] Python lists are actually arrays, not lists
+
+.. [#] If you don't know Scheme,
+
+ [1, 2] (ML) => [1,[2,[]]] (Python)
+
+
+
+It is also possible to apply a binary operator to a list, via the ``foldl`` and ``foldr``
+functions::
+
+ - val sum = foldl op+ 0 [1,2,3];
+ val sum : int = 6
+
+
+fun enum n = lazy n :: enum (n+1)
+
+(for instance, a log file); how can we process it? The simplest possibility is
+to convert it into a lazy list of lines, with the following code::
+
+ fun textFileToList filename = let
+ val file = TextIO.openIn filename
+ fun lazy readLines () =
+ case TextIO.inputLine file
+ handle ex => (TextIO.closeIn file; raise ex)
+ of NONE => (TextIO.closeIn file; [])
+ | SOME line => line :: readLines ()
+ in
+ readLines ()
+ end
+
+
+A smarter line counter
+-----------------------------------------------------------
+
+ - val countLines = length o textFileToList
+
+
+
+
+Python extended generators in Alice
+---------------------------------------------------------
+
+def consumer():
+ result = []
+ while True:
+ inp = yield
+ if inp = END:
+ return result
+
+functor consumer(val ch: channel):
+ while true do let
+ val inp = Channel.gexst ch
+ if inp = END:
+
+
+In particular, what's the equivalent of the simple
+Python one-liner ``for item in container: print item``? The answer is
+that there is no equivalent. The Python one-liner is completely
+polymorphic, since it works for any kind of container and it is able
+to print any kind of object. However, SML is a statically typed
+language, and you must give to the compiler some information about the
+types: it cannot predict the future, nor the type of the container and
+the types of the items. Here I will show how you can loop on
+homogenous containers, i.e . containers where the items are all
+instances of the same type;
+
+
+ fun writeln (tostring, value) =
+ print(format (tostring o text "\n") value);
+
+
+- app (fn item => writeln(int, item)) [1,2,3];
+1
+2
+3
+
+fun sum lst = foldl op+ 0 lst
+
+The thing to remember is that functions associate to the **right**, so
+
+ ``a -> b -> c``
+
+means
+
+ ``a -> (b -> c)``
+
+whereas type constructor associates to the **left**, so
+
+ ``int ref list``
+
+means
+
+ ``(int ref) list``
+
+
+Timers
+--------------------
+
+fun timedFn f a = let
+ val ct = Timer.startRealTimer ()
+ val result = f a
+in
+ (result, Timer.checkRealTimer (ct))
+end
+
+
+ - structure A = struct
+ type 'a aggr
+ fun length(a: 'a aggr) = 1
+ fun sub(a: 'a aggr, i :int) = 1
+ end;
+ signature AGGREGATE_TYPE =
+ sig
+ type 'a aggr
+ val length : 'a aggr -> int
+ val sub : 'a aggr * int -> int
+ end
+ -
+
+ok
+
+"Hello World", part II
+-------------------------------------------------
+
+On the other hand, print2 cannot accept anything different than strings::
+
+ - print2("the answer is ", 42);
+ 1.0-1.28: mismatch on application: expression type
+ string * int
+ does not match function's argument type
+ string * string
+ because type
+ int
+ does not unify with
+ string
+
+To print a string and a number, we should define another function::
+
+ - fun print_string_int(s, i)=(print s; print (Int.toString(i)));
+ val print_string_int : string * int -> unit = _fn
+ - print_string_int("The answer is ", 42);
+ The answer is 42val it : unit = ()
+
+This is clearly unpractical, since we can't define an infinite number
+of ``print`` functions to be able to print all the potentially
+infinite types we can have in our programs. Fortunately there are
+utility library for converting objects in strings (even if not
+standard :-(). SML/NJ has the library FormatComb, to be used as
+follows (from now on, for concision sake, I will omit to write down
+the full output of the REPL)::
+
+ - open FormatComb;
+ - print (format (text "The value is " o int o text ".") 42);
+ The value is 42
+
+The syntax looks strange (especially the "o" operator) and if you
+forget the parenthesis you will get funny error messages. To
+understand what is going on, you will need to master SML to a much
+more advanced level than this first paper is meant to, so you will
+have to wait for "Hello World, Part II" ;) Here I will content myself
+to notice that the format utility requires you to specify the types of
+the arguments. SML is a *typeful* language: the compiler must know the
+types of all your variables *before running the program*. In a
+dynamic language, instead, the types can be introspected at runtime
+and there is no need to specify them. This is most of the times an
+advantage, however, it also leads to type errors that cannot occur in
+a statically typed language such as SML (also called *type safe*
+languages). Moreover, SML compilers may perform optimization which are
+impossible in a dynamic language (but this is of lesser relevance,
+since any user of dynamic languages will use C libraries if speed is
+an issue).
+
+----
+
+
diff --git a/ml/article5.txt b/ml/article5.txt
new file mode 100644
index 0000000..24719d3
--- /dev/null
+++ b/ml/article5.txt
@@ -0,0 +1,44 @@
+Records
+-----------------------
+
+The first level of grouping in ML is the record level: a record
+roughly correspond to a *struct* in the C programming language and can
+contain any kind of first class value. The record itself a first class value,
+i.e. it can be passed to and returned from functions. I will give a few
+examples of usage.
+
+A record factory::
+
+ - fun makeArticle {title:string, author:string} = {title, author};
+ val makeArticle : {author : string, title : string} -> {author : string, title : string} = _fn
+
+An example record::
+
+ - val article = makeArticle {title="Functional Programming", author="M. Simionato"};
+ val article : {author : string, title : string} =
+ {author = "M. Simionato", title = "Functional Programming"}
+
+Extracting fields from a record::
+
+ - #title article;
+ val it : string = "Functional Programming"
+ - #author article;
+ val it : string = "M. Simionato"
+
+A record containing functions::
+
+ - val a = {makeArticle, printArticle = fn {title, author} => print (title^" "^author ^"\n") };
+ - #printArticle a article;
+ Functional Programming M. Simionato
+
+Notice that the order of the fields is not specified and that there is no
+concept of subrecord; for instance two records of kind
+``{title:string, author:string, publicationDate:string}`` and
+``{title:string, author:string}``
+are considered completely different record types, the second one is not a subtype of
+the first one and you cannot substitute one with the other, possibly with default
+values. Also, records are purely static and resolved at compile time: if you need
+something more dynamic, you should use a map, not a record. Finally, records
+are functional, i.e. immutable: there is no way to change the value of a field,
+you must create an entirely new record with a different value if you want to
+simulate a record update.