Mercury
1995Mercury is a pure logic programming language that combines the power of Prolog with static typing and functional programming features. It was designed at the University of Melbourne for building large, reliable, and efficient applications.
About Mercury
Mercury is known for its:
- Strong static typing: Type errors are caught at compile time
- Mode system: Ensures variables are used correctly
- Determinism system: Specifies whether predicates succeed, fail, or produce multiple solutions
- Functional and logic programming: Supports both paradigms seamlessly
- High performance: Compiles to efficient C code
Features
Mercury combines the expressiveness of logic programming with the safety of strong typing. The language uses a sophisticated type, mode, and determinism system to ensure program correctness at compile time.
The Mercury compiler generates efficient C code and provides excellent error messages, making it suitable for large-scale software development.
Hello World Explained
:- module hello_world.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
main(!IO) :-
io.write_string("Hello World!", !IO).:- module hello_world.- Declares the module name:- interface.- Begins the public interface section:- import_module io.- Imports the I/O module:- pred main(io::di, io::uo) is det.- Declares main as a deterministic predicatemain(!IO) :-- Uses state variables for I/O threadingio.write_string("Hello World!", !IO)- Outputs the string
Learn More
Hello World
#!/bin/sh
# If this file is present, this is the file that runs when you add the
# RUN=1 option.
#
# Otherwise, the default behavior is to run the first file in the
# directory that matches the pattern `hello-world.*``.
# Build it
# Run it
# Compile and run the Mercury program
cd /hello-world
mmc --make --no-verbose-make -w hello_world
./hello_world "$@"Coding Guide
Language Version
Mercury compiler (mmc) - latest available in Alpine
Execution Model
- Compiled language using
mmc(Mercury compiler) - Code is compiled to a binary, then executed
- Standard Mercury execution model with
main(io::di, io::uo)predicate
Key Characteristics
- Pure logic programming language with static typing
- Strong type system with type inference
- Mode system: specifies input/output modes for predicates (e.g.,
di= destructive input,uo= unique output) - Determinism system: specifies whether predicates are
det(deterministic),semidet(semi-deterministic),nondet(non-deterministic), ormulti(multi-solution) - State variables (
!IO) for threading I/O state - Module system with interface and implementation sections
- Pattern matching
- Higher-order predicates
- Case-sensitive
- Predicates end with a period (
.) - Uses
:-for declarations and rules
Fragment Authoring
Your fragment provides the complete interface and implementation sections for a pre-existing module. Include your own :- interface., :- import_module, :- pred main(io::di, io::uo) is det., :- implementation., and the main predicate definition.
Available Libraries
Standard Mercury modules can be imported as needed:
io- I/O operations:io.write_string(String, !IO)- Write a stringio.write(Value, !IO)- Write a valueio.nl(!IO)- Write a newlineio.print(Value, !IO)- Print a valueio.format(FormatString, Args, !IO)- Formatted output
int- Integer operations (arithmetic operators like+,-,*,/)list- List operations (list.map,list.filter,list.foldl, etc.)string- String operations (string.append,string.length, etc.)
Additional modules can be imported in the interface section if needed:
float- Floating-point operationsmath- Mathematical functionssolutions- Solution handling for non-deterministic predicates- And many more from the Mercury standard library
Common Patterns
- Output:
io.write_string("Hello World!\n", !IO) - Multiple statements: Use
,to sequence goals:Goal1, Goal2, Goal3 - Variables:
X = 5(unification) - Predicates:
predicate_name(Arg1, Arg2, !IO) :- Body. - Pattern matching:
[Head | Tail]for lists,{X, Y}for tuples - Conditionals:
( Condition -> Then ; Else ) - Loops: Use recursion or higher-order predicates like
list.foldl - State variables:
!IOfor I/O state,!Statefor custom state - List operations:
list.map,list.filter,list.foldl,list.length - String concatenation:
string.append(String1, String2, Result)
Examples
% Simple output
main(!IO) :-
io.write_string("Hello from fragment!\n", !IO).
% Variables and calculations
main(!IO) :-
A = 5,
B = 10,
Sum = A + B,
io.write_string("Sum: ", !IO),
io.write_int(Sum, !IO),
io.nl(!IO).
% Helper predicates
:- pred add(int::in, int::in, int::out) is det.
add(X, Y, Sum) :-
Sum = X + Y.
main(!IO) :-
add(5, 10, Result),
io.write_string("5 + 10 = ", !IO),
io.write_int(Result, !IO),
io.nl(!IO).
% Pattern matching with lists
:- pred sum_list(list(int)::in, int::out) is det.
sum_list([], 0).
sum_list([Head | Tail], Sum) :-
sum_list(Tail, TailSum),
Sum = Head + TailSum.
main(!IO) :-
Numbers = [1, 2, 3, 4, 5],
sum_list(Numbers, Total),
io.write_string("Sum: ", !IO),
io.write_int(Total, !IO),
io.nl(!IO).
% String operations
main(!IO) :-
S = "Hello",
string.append(S, " World!", T),
io.write_string(T, !IO),
io.nl(!IO),
string.length(T, Len),
io.write_string("Length: ", !IO),
io.write_int(Len, !IO),
io.nl(!IO).
% Conditionals
:- pred absolute(int::in, int::out) is det.
absolute(X, Y) :-
( X >= 0 ->
Y = X
;
Y = -X
).
main(!IO) :-
absolute(-5, Result),
io.write_string("Absolute of -5: ", !IO),
io.write_int(Result, !IO),
io.nl(!IO).
% Higher-order predicates
main(!IO) :-
Numbers = [1, 2, 3, 4, 5],
list.map(double, Numbers, Doubled),
io.write_string("Doubled: ", !IO),
io.print(Doubled, !IO),
io.nl(!IO).
:- pred double(int::in, int::out) is det.
double(X, Y) :-
Y = X * 2.Caveats
- Fragments must be valid Mercury code that compiles
- Remember that Mercury is case-sensitive
- All predicates must end with a period (
.) - State variables (
!IO) must be threaded through all I/O operations - Mode declarations are required for predicates (though often inferred)
- Determinism declarations are required (though often inferred)
- Use
=for unification (not assignment) - String concatenation uses
string.append, not++ - Use
io.write_intfor integers,io.write_stringfor strings - Pattern matching uses
[Head | Tail]for lists - Conditionals use
( Condition -> Then ; Else )syntax - Helper predicates must be defined before they are used (or declared in interface)
- The
mainpredicate must have modemain(io::di, io::uo) is det.