[mercury-users] Again exceptions (patternmatch & devide-by-zero)

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Dec 4 20:58:41 AEDT 2002


On 04-Dec-2002, xkb at hypernation.net <xkb at hypernation.net> wrote:
> I dont't know if merucry supports pattern matching, though I think it does.

It does, though not in the same way as in most functional languages.
The treatment of non-exhaustive or non-exclusive patterns is different.

> Pattern matching is often used in functional programming languages to offer
> case distinction.
> 
> An example from Haskell:
> 
> f :: Int -> Int
> f x =
>  | 0 = Error(0)
>  | >0 = 10/x

This is actually not valid Haskell for a variety of reasons.
Also, this example uses guards (the "|" notation), not pattern matching.

Mercury supports pattern matching, but does not have any syntax similar
to Haskell's guards.  For programs where in Haskell you might use the guard
syntax, in Mercury you would just use an if-then-else.

> Let assume someone would call f(-10), as the patterns indicated by the |'s are
> not exhaustive, an error will occur: Pattern match not exhaustive. Does this
> kind of behaviour throw an exception in mercury?

If the procedure is declared with a determinism in which failure
is allowed, then non-exhaustive patterns will result in failure and
subsequent backtracking to the previous choice point.  If the procedure
is declared with a determinism in which failure is not allowed, then
non-exhaustive patterns will result in a determinism error at compile
time.  This can be remedied by adding a clause which matches the missing
pattern and throws an exception.

Some examples:

	% compile-time error
	:- func f2(bool) = int.
	:- mode f2(in) = out.
	f2(yes) = 42.

	% run-time error
	:- func f3(bool) = int.
	:- mode f3(in) = out is det.
	f3(yes) = 42.
	f3(no) = _ :- error("got a no").

	% valid, results in "failure" (i.e. backtracking) at run-time
	:- func f1(bool) = int.
	:- mode f1(in) = out is semidet.
	f1(yes) = 42.

	:- pred p(int).
	:- mode p(out) is multi.
	p(X) :-
		% execution will bind B to no, call f1, fail,
		% backtrack to the second disjuct here, bind B to yes,
		% call f1, and succeed with X = 42.
		(B = no ; B = yes),
		X = f1(B).

	main -->
		% this prints "[42]"
		solutions(p, List),
		print(List), nl,

		% this prints "no"
		% execution will "backtrack" from the condition
		% of the if-then-else to the else part.
		(if some [X] { X = f1(no) } then
			print(X)
		else
			print("nope"), nl
		).

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list