As we probably all know, monads are handy programming constructs
that let us express different "execution environments" and operations
therein in a uniform way. Every monad gives the programmer some kind of
an environment where it is possible perform arbitrary
computations in the ordinary way, while the monad controls the workings
of the environment and usually provides some additional services
specific to that environment. For instance, the ''state monad''
provides an environment with two additional services, storing a value
for later reference and querying the stored value. The monad takes care
of threading this stored value through the whole computation, including
recursive calls, etc. Any kind of effect that could be achieved through
"side effects" (violations of functional purity) can be modelled as
services in a monad that is specifically designed to be able to provide
those services.
[...]
Monadic parsers are a prime example. example of
monadic composition. A parser is a function that takes an "input
stream" (a string, for instance), and returns a value (the result of
parsing the beginning of the input stream) and an updated input stream,
with the already parsed content removed. {{{ parseInt "300 square
meters" ==> (300, " square meters") }}} The input stream can be seen as
a state which is inspected by various parsing operations (for finding
out the result of parsing) and updated (by dropping elements from the
beginning). It must be threaded (with updates and all) through the
whole parsing computation, so it is useful to use the state monad to
handle the input stream.
But, it also happens that parsers are functions that can ''fail''
under invalid input. For instance, the result of parseInt "you suck"
should probably not be any trash integer but rather a value denoting
failure. So a parser is also and an instance of
the so called ''exception monad'', a monad whose sole service is to
give a possibility to abort the computation and return nothing. (The
exception monad can also provide some service to perform "alternative
computations", trying out another computation in case the first one
fails.) {{{ parseInt "300 square meters" ==> Just (300, " square
meters") parseInt "you suck" ==> Nothing }}} (People who know the
related literature will yell at me for introducing the exception monad,
instead of the indeterminism monad, here. Let it be just for the sake
of demonstration, right?)
[...]
The downside, of course, is that you can't use the services provided
by the existing monads but you'll have to write wrapper services for
those the services, in addition to the
definitions of bind (>>=) and return.
[...]
[kategoria: ohjelmointi] [kategoria: keskeneräiset]