mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 01:43:35 +00:00
library/enum.m:
As above.
NEWS.md:
Announce this breaking change.
library/bool.m:
library/char.m:
library/int.m:
library/term.m:
library/uint.m:
tests/hard_coded/deep_copy_exist.m:
tests/typeclasses/extract_typeinfo2.m:
Conform to the change in enum.m.
compiler/pred_table.m:
When typechecking leaves am ambiguity unresolved, a predicate
in this module used to pick one of the candidate matches effectively
at random to "resolve" it.
After the change to enum.m, this led to a compiler abort when compiling
uint.m. The ambiguity was between uint.from_int/2 and the new
enum.from_int/2. The old algorithm picked enum.from_int/2, and tried
to look up its class constraints in the current class context; this failed
with an abort, because the current class context was empty.
Fix this by choosing the match (or *a* match) with the fewest typeclass
constraints to "resolve" any ambiguities.
tests/invalid/overload_resolution_preference.{m,err_exp}:
A test case for the change to pred_table.m.
tests/invalid/Mmakefile:
Enable the new test case.
tests/invalid_submodules/unresolved_overloading.err_exp:
Update this expected output after the change to pred_table.m.
98 lines
3.3 KiB
Mathematica
98 lines
3.3 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2000, 2005-2006 The University of Melbourne.
|
|
% Copyright (C) 2014-2015, 2017-2018, 2022 The Mercury team.
|
|
% This file is distributed under the terms specified in COPYING.LIB.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: enum.m.
|
|
% Author: stayl.
|
|
% Stability: medium
|
|
%
|
|
% This module provides the typeclass enum, which describes types
|
|
% which can be converted to and from integers without loss of information.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module enum.
|
|
:- interface.
|
|
|
|
% A type T can be declared to be a member of the enum typeclass if
|
|
%
|
|
% - all values X of type T can be converted to an int N using
|
|
% the instance's to_int member function, with each distinct X
|
|
% being translated by to_int to a distinct N; and
|
|
%
|
|
% - for all values N of type int that are equal to to_int(X) for some X,
|
|
% from_int(N) = X.
|
|
%
|
|
% - for all values N of type int that are not equal to to_int(X) for any X,
|
|
% from_int(N) should fail.
|
|
%
|
|
% In mathematical notation, the following must hold:
|
|
%
|
|
% all [X] (X = from_int(to_int(X)))
|
|
% all [X, Y] (to_int(X) = to_int(Y)) => X = Y)
|
|
% all [N] (some [X] N = to_int(X) => from_int(N) = X)
|
|
% all [N] (not (some [X] N = to_int(X))) => from_int(N) fails
|
|
%
|
|
:- typeclass enum(T) where [
|
|
func to_int(T) = int,
|
|
pred from_int(int::in, T::out) is semidet
|
|
].
|
|
|
|
% This is another version of the above typeclass, which maps
|
|
% values of type T to *unsigned* integers.
|
|
%
|
|
% The other difference is that the from_uint method is a semidet
|
|
% *predicate*, not a semidet *function*. This is because programmers
|
|
% are more likely to expect predicates to be able to fail than functions.
|
|
%
|
|
:- typeclass uenum(T) where [
|
|
func to_uint(T) = uint,
|
|
pred from_uint(uint::in, T::out) is semidet
|
|
].
|
|
|
|
% The from_int method of the enum typeclass used to be a semidet function.
|
|
% This function is here to provide backwards compatibility, for a limited
|
|
% time, for code that uses that old method.
|
|
%
|
|
:- func from_int(int) = T is semidet <= enum(T).
|
|
:- pragma obsolete(func(from_int/1)).
|
|
|
|
% det_from_int(I) returns the result of from_int(I), but throws an
|
|
% exception if from_int fails.
|
|
%
|
|
:- func det_from_int(int) = T <= enum(T).
|
|
:- func det_from_uint(uint) = T <= uenum(T).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module require.
|
|
|
|
from_int(I) = X :-
|
|
from_int(I, X).
|
|
|
|
det_from_int(I) = X :-
|
|
( if from_int(I, X0) then
|
|
X = X0
|
|
else
|
|
unexpected($pred, "from_int failed")
|
|
).
|
|
|
|
det_from_uint(U) = X :-
|
|
( if from_uint(U, X0) then
|
|
X = X0
|
|
else
|
|
unexpected($pred, "from_uint failed")
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module enum.
|
|
%---------------------------------------------------------------------------%
|