summaryrefslogtreecommitdiff
path: root/ml
diff options
context:
space:
mode:
authormicheles <micheles@micheles-mac>2010-05-22 14:27:00 +0200
committermicheles <micheles@micheles-mac>2010-05-22 14:27:00 +0200
commit90358f59174cd8fdb7af2e843770923f4a879b22 (patch)
treee77187abb2d2bf32fdf1874308e6b1195fd00393 /ml
parent6580b54798adc3a4abb110cb7045eb42346cf68c (diff)
downloadmicheles-90358f59174cd8fdb7af2e843770923f4a879b22.tar.gz
Fixed grammar
Diffstat (limited to 'ml')
-rw-r--r--ml/comb.txt36
-rw-r--r--ml/intro.txt2
-rw-r--r--ml/loops.txt95
-rw-r--r--ml/modules.txt32
-rw-r--r--ml/objects.txt3
-rw-r--r--ml/text.txt18
-rw-r--r--ml/types.txt31
7 files changed, 115 insertions, 102 deletions
diff --git a/ml/comb.txt b/ml/comb.txt
index dea4e43..4abb68c 100644
--- a/ml/comb.txt
+++ b/ml/comb.txt
@@ -80,15 +80,16 @@ are a few differences.
at the lottery and decided to leave for a tropical paradise, nobody would
provide support for Alice ML on the mailing list
-4.
- SML is a deserted language, even compared to non-mainstream languages
- as OCaml, Haskell, Scheme, Common Lisp, Smalltalk, Tcl, ...; it is perhaps the
- least used language I have ever seen and this is a pity.
+4.
+ SML is a deserted language, even compared to non-mainstream
+ languages as OCaml, Haskell, Scheme, Common Lisp, Smalltalk, Tcl,
+ ...; it is perhaps the least used language I have ever seen and
+ this is a pity.
-5.
- Generally speaking, if you want bindings for external libraries you have to write
- it yourself; there are no standard bindings for GUI toolkits, database drivers,
- scientific programming libraries.
+5.
+ Generally speaking, if you want bindings for external libraries
+ you have to write it yourself; there are no standard bindings for
+ GUI toolkits, database drivers, scientific programming libraries.
6.
Scripting languages have traditionally a strong support for Web programming
@@ -167,10 +168,10 @@ nested Python list, i.e.
.. _basis library: http://www.standardml.org/Basis/list.html
-The core of the algorithm used in the interpolation library is a recursive function
-which takes a list of N+1 terms ``t_1 ... t_{N+1}`` and a list of N arguments
-``a_1 .. a_N`` and returns the string obtained by interspersing the terms
-with the arguments,
+The core of the algorithm used in the interpolation library is a
+recursive function which takes a list of N+1 terms ``t_1 ... t_{N+1}``
+and a list of N arguments ``a_1 .. a_N`` and returns the string
+obtained by interspersing the terms with the arguments,
``t_1 ^ a_1 ^ ... _tN ^ a_N ^ t_{N+1}``
@@ -269,11 +270,12 @@ celestial operators back to earthly strings::
- fun l O = O Fn. id "";
val l : (('a -> 'a) -> string -> 'b) -> 'b = _fn
-``l`` takes the operator, applies it to the identity function and returns a function
-which is then applied to the empty string, finally bringing back at home a
-plain string; ``l`` is the inverse of ``L``, i.e. ``l o L`` is the identity
-in the space of strings where ``L o l`` is the identity in the space
-of operators. You can try yourself at the prompt that
+``l`` takes the operator, applies it to the identity function and
+returns a function which is then applied to the empty string, finally
+bringing back at home a plain string; ``l`` is the inverse of ``L``,
+i.e. ``l o L`` is the identity in the space of strings where ``L o l``
+is the identity in the space of operators. You can try yourself at the
+prompt that
::
diff --git a/ml/intro.txt b/ml/intro.txt
index bda328b..2e710ed 100644
--- a/ml/intro.txt
+++ b/ml/intro.txt
@@ -105,7 +105,7 @@ they just make everything immutable. Making everything immutable has
big advantages especially in multithreaded programming, since
different threads cannot interfere each other and you can just forget
about locks. On the other hand, various programming patterns based on
-mutability (for instance keeping a registry of callbacks) becames
+mutability (for instance keeping a dynamic registry of callbacks) becames
impossible.
Another very common operation in imperative languages is rebinding a variable.
diff --git a/ml/loops.txt b/ml/loops.txt
index a3c2144..5dc22c0 100644
--- a/ml/loops.txt
+++ b/ml/loops.txt
@@ -118,8 +118,8 @@ Loops and recursion
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
+section I will explain why and the way to work around this omission.
+To begin 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 [#]_::
@@ -176,17 +176,18 @@ Return the new value of the counter::
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
+to suggest you 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*.
+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::
+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
@@ -215,14 +216,15 @@ 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);
+ | 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::
+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);
+ 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.
@@ -248,9 +250,9 @@ language, it is possible to write::
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) [#]_ .
+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
@@ -269,10 +271,11 @@ 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. 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
@@ -330,18 +333,19 @@ natural to define a higher order function such as the following::
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::
+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
@@ -351,18 +355,19 @@ 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 equivalent higher order functions 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 ;)
+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 equivalent higher order functions 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 ;)
----
diff --git a/ml/modules.txt b/ml/modules.txt
index 0775bbe..d235f57 100644
--- a/ml/modules.txt
+++ b/ml/modules.txt
@@ -200,9 +200,10 @@ and should be done with care.
Structures are not first class values
-----------------------------------------------------------
-The problem with structures is that they are not first class values, i.e. 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::
+The problem with structures is that they are not first class values,
+i.e. 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'
@@ -332,24 +333,25 @@ the signature to a concrete structure::
val sub : 'a Vector.t * int -> 'a
end = Vector
-i.e. the abstract type ``t`` is replaced by the concrete type ``list`` when the
-signature is ascribed to the ``List`` structure and by the concrete type ``vector``
-when the signature is ascribed to the ``Vector`` structure.
-Moreover, having ascribed the ``SIMPLE_SEQUENCE`` signature to the
-structures ``L`` and ``V``, we have automatically hidden all the additional
-functionality of the original structures, so that for instance ``L.map``
-and ``V.map`` are not accessible, even if ``List.map`` and ``Vector.map``
-do exists::
+i.e. the abstract type ``t`` is replaced by the concrete type ``list``
+when the signature is ascribed to the ``List`` structure and by the
+concrete type ``vector`` when the signature is ascribed to the
+``Vector`` structure. Moreover, having ascribed the
+``SIMPLE_SEQUENCE`` signature to the structures ``L`` and ``V``, we
+have automatically hidden all the additional functionality of the
+original structures, so that for instance ``L.map`` and ``V.map`` are
+not accessible, even if ``List.map`` and ``Vector.map`` do exists::
- L.map
1.2-1.5: unknown value or constructor `map'
- V.map;
1.2-1.5: unknown value or constructor `map'
-In a sense, you may see ascribing the signature as a way of importing a selected
-subset of the functionality of the original structure; you could even import a subset
-of the names defined in the original structures in the current namespace
-by opening the ascribed structure::
+In a sense, you may see ascribing the signature as a way of importing
+a selected subset of the functionality of the original structure; you
+could even import a subset of the names defined in the original
+structures in the current namespace by opening the ascribed
+structure::
- open Vector:SIMPLE_SEQUENCE;
structure _id20 :
diff --git a/ml/objects.txt b/ml/objects.txt
index ceda7b8..f6d4f47 100644
--- a/ml/objects.txt
+++ b/ml/objects.txt
@@ -185,7 +185,8 @@ systems; consider for instance this example::
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)::
+We can get the same effect via a stateful higher order function
+(a.k.a. a closure)::
exception MissingMethod
diff --git a/ml/text.txt b/ml/text.txt
index 97856a6..870d056 100644
--- a/ml/text.txt
+++ b/ml/text.txt
@@ -16,15 +16,15 @@ that Haskell.
Text processing in SML
----------------------------------------------
-Scripting languages, starting from Perl, have a very strong tradition in the field
-of text processing. In comparison, SML has very primitive libraries. Still, it is
-not difficult to implement a few basic facilities. In this assessment, as a
-learning exercise, I will show how can implement a simple template mechanism.
-In order to do so, the first thing to discuss is the regular expression.
-More or less all SML implementations have they own regular expression
-library; here I will consider only Alice ML library, which is very simple
-and needs to be supplemented by some utility in order to become
-usable.
+Scripting languages, starting from Perl, have a very strong tradition
+in the field of text processing. In comparison, SML has very few
+primitive text processing functions. Still, it is not difficult to implement a few
+basic facilities. In this assessment, as a learning exercise, I will
+show how can implement a simple template mechanism. In order to do
+so, the first thing to discuss is the regular expression. More or
+less all SML implementations have they own regular expression library;
+here I will consider only Alice ML library, which is very simple and
+needs to be supplemented by some utility in order to become usable.
$pippo:
$hello
diff --git a/ml/types.txt b/ml/types.txt
index f7f54f2..2f38359 100644
--- a/ml/types.txt
+++ b/ml/types.txt
@@ -77,7 +77,7 @@ For instance, suppose you want to define an utility function casting integer to
You can do so as follows::
- fun valueToString (INT x) = Int.toString x
- | valueToString (STR x) = x;
+ | valueToString (STR x) = x;
val valueToString : int_or_string -> string = _fn
Let me check that it works::
@@ -138,9 +138,10 @@ a pair ``(string, int)`` as input::
- STRING_INT;
val it : string * int -> string_int = _fn
-Moreover, SML allows to define recursive types. For instance, a file system is a typical
-example of recursion, since directories can contains directories at any
-level of nesting. It can modeled with the following recursive datatype::
+Moreover, SML allows to define recursive types. For instance, a file
+system is a typical example of recursive data structure, since
+directories can contains directories at any level of nesting. It can
+modeled with the following recursive datatype::
- datatype file_or_dir = File of string | Dir of string * file_or_dir list
datatype file_or_dir = Dir of string * file_or_dir list | File of string
@@ -186,8 +187,8 @@ enumeration types, like the following one::
- datatype color = RED|GREEN|BLUE;
datatype color = BLUE | GREEN | RED
-For enumeration types the name "constructor" is rather improper, since constructor are
-just values::
+For enumeration types the name "constructor" is rather improper, since
+constructor are just values::
- RED;
val it : color = RED
@@ -224,7 +225,8 @@ can define ::
In technical terms, we say that SML support *parametric polymorphism*.
-Notice that it is pretty easy to define a function extracting the inner value from a box::
+Notice that it is pretty easy to define a function extracting the
+inner value from a box::
- fun unbox (Box x) = x;
@@ -276,7 +278,7 @@ Possibly the most used word in statically typed languages is *polymorphism*.
The word does not exist in dynamic languages, since dynamically typed languages
are polymorphic by design, whereas in statically typed languages you have
to work to achieve polymorphism, i.e. the ability to define functions accepting
-generic types. In order to give a poor man' example, suppose we want to
+generic types. In order to give a poor man example, suppose we want to
define a few polymorphic utilities accepting both lists and vectors. We could
do so by defining a ``ListOrVector`` structure associated with a
``list_or_vector`` datatype::
@@ -320,7 +322,7 @@ introduce functors with a motivating example, again in the arena of
input and output.
We saw in an earlier installament that the standard library provides two
structures ``TextIO`` and ``BinIO`` for managing text files and binary
-files respectively; we also show that the two structures have many things
+files respectively; we also saw that the two structures have many things
in common, and it is possibile to define a (sub)signature matching both.
@@ -328,7 +330,7 @@ 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
+taking structures in input and returning structures in output. Functors
are not-first-class objects themselves and therefore they require a specific
declaration ``functor Name(Struct:SIGNATURE) = funct ... end``.
@@ -348,10 +350,11 @@ by writing::
- structure T = ManagedIO(TextIO)
- structure B = ManagedIO(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.
+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.
``- T.withInputFile "three-lines.txt" (print o T.inputAll)``