You can download mercury from the mercury downloads page.
Installation is pretty simple:
/usr/local/src
$ ./configure
- here you can also enable or disable grades
(target platforms), but let’s go with the defaults for now - it will
be enough for this tutorial.$ make
unfortunately this will take a long time - so if
you have multiple cores available instead run: $ make -j2
(or 2,
or 4, 6, 8 - depending on the number of cores you have)$ sudo make install
again this can take quite a while so
running it with -jN
is quite a good idea.If everything went alright you should be able to call:
$ mmc --version
On my system this prints out:
Mercury Compiler, version 14.01, configured for x86_64-unknown-linux-gnu
Copyright (C) 1993-2014 The University of Melbourne
If you’ve got any errors then something went wrong - check the outputs of configure and/or make.
Before we can discuss hello world there’s one more thing we need to
discuss. In the previous article we talked about the in
and out
modes that a predicate can have. Now we’ll talk about di
(Destructive Input) and uo
(Unique Output) modes.
Modes are defined in mercury as relations between instatnation states. As of now we known about two instatnation states: free and ground.
An in
mode declares that this predicate expects a free variable
before unification and that variable will be ground after. We can
succinctly write out all modes that are of interest for now1
:- mode in == ground >> ground
:- mode out == free >> ground
:- mode di == unique >> clobbered
:- mode uo == free >> unique
We see two unknown instantiation states here: unique and clobbered. The two are duals to each other in the same way that free and ground are. We can think of the di mode the same way we think of the in mode with one very important distinction: when you unify a unique variable it becomes clobbered. clobbered is an instantation state that cannot be unified again - trying to unify a clobbered variable will result in a compile-time error.
This may seem a little strange but we’ll see what this is for shortly.
Effects and side-effects are really hard to define. I’ve tried tackling this subject in an article, but here I will try to appeal to the intuition.
A side-effect is everything that breaks equation reasoning i.e the program cannot be interpreted as a series of substitutions anymore.
While we can program imperative languages so that they don’t break equational reasoning (i.e don’t introduce side effects) the ability to introduce side effects is inherent to all imperative languages. Side effects may include:
Defining effects is trickier - while we might say that an effect is an controlled effect I’d like to propose another (layman) definition: an effect is a value that needs a special interpreter (usually in the form of a compiler library) that when interpreted will directly affect state, values or the “physical world”.
This definition will come in handy soon. I promise.
Mercury, like haskell doesn’t allow side-effects. As you might have guessed by the previous section controlling effects in mercury is done through the di and uo modes.
To start we will be interested in only one effect: printing to the screen. For an example let’s proceed to the hello world program.
A minimal program in mercury has some ceremony behind it. This is hello world:
Btw you can find the full code here
To compile it we simply run:
$ mmc hello_world
And then run
$ ./hello_world
If all is well you should have successfully said hello to the world. Now let’s analyze the program.
Mercury code is located inside modules. A module must have a name. The line:
Declares the hello_world
module. Next line:
Declares the start of the interface section.
In the interface section we import the io
module - we need that for
the io
type (used by the main
predicate).
main
predicate.
main
in mercury is special the same way that main
in C is
special. It’s the default method that mercury tries to call (or
rather expects in a executable).The next lines do just that - declare the main
predicate and its mode
and end the interface section (by starting the implementation section).
Finally we get the implementation of main:
The effect of io.write_string
is writing a string to the output
stream.
The way we can think of io and effects is that the io
type (used in
the main predicate) accumulates the “changes” (or effects) that need to
be done. Then after main
unifies the resulting io
type is
interpreted (by some abstract mercury runtime).
In our hello_world
program the resulting io
type only “contains” one
io action: printing out “Hello world!\n” - but in general it can have
much more (reading from stdin, creating files, reading files etc).
What’s important that this is may not be how real mercury programs will execute but because it the end this will be exactly the same as if they would we can think of them in this way - and that’s very powerful because it preserves equational reasoning of programs.
In the next part we will actually start implementing the first parts of our scheme interpreter. Stay tuned!
this is actually straight out of the documentation and the
syntax :- mode X == Y.
is how mercury defines its modes. We can
take a look at builtin.m
or its online documentation: documentation to see all the modes in their glory. ↩