[mercury-users] Types as sets?
Fergus Henderson
fjh at cs.mu.OZ.AU
Tue Feb 11 16:47:54 AEDT 2003
On 11-Feb-2003, Douglas Auclair <dauclair at msn.com> wrote:
> Another way of stating the problem is that, for example, I know that a
> particular variable is constrained to a subset of values of another type,
> but the compiler doesn't know this, and I wish to create a new type that
> reflects this knowledge, so that:
>
> :- pred p(two_digit_natural::in, string::out) is det.
> p(1, "one").
> % ...
> p(99, "ninety-nine").
>
> will compile (I know the above is a silly example, but I do run into this
> kind of problem quite often and I prefer the declarative syntax to the
> if-then-else (i.e. ->) spagetti-nested mess).
>
> Is there a way, currently, to create the type two_digit_natural that will
> allow the above code to compile?
In Mercury, subtypes can be represented using the mode system.
You can write this as
:- pred p(int::in(two_digit_natural), string::out) is det.
p(1, "one").
% ...
p(99, "ninety-nine").
where `two_digit_natural' is an inst that represents the subtype,
defined by
:- inst two_digit_natural --->
0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 ;
10 ; 11 ; 12 ; 13 ; 14 ; 15 ; 16 ; 17 ; 18 ; 19 ;
20 ; 21 ; 22 ; 23 ; 24 ; 25 ; 26 ; 27 ; 28 ; 29 ;
30 ; 31 ; 32 ; 33 ; 34 ; 35 ; 36 ; 37 ; 38 ; 39 ;
40 ; 41 ; 42 ; 43 ; 44 ; 45 ; 46 ; 47 ; 48 ; 49 ;
50 ; 51 ; 52 ; 53 ; 54 ; 55 ; 56 ; 57 ; 58 ; 59 ;
60 ; 61 ; 62 ; 63 ; 64 ; 65 ; 66 ; 67 ; 68 ; 69 ;
70 ; 71 ; 72 ; 73 ; 74 ; 75 ; 76 ; 77 ; 78 ; 79 ;
80 ; 81 ; 82 ; 83 ; 84 ; 85 ; 86 ; 87 ; 88 ; 89 ;
90 ; 91 ; 92 ; 93 ; 94 ; 95 ; 96 ; 97 ; 98 ; 99.
We have been working on a plan to provide nicer syntax for this
sort of thing; search the Mercury mailing list archives for
"subtype proposal" for more details.
> Another workaround that I've used commonly is to declare a helper predicate
> as (cc_)multi to a det main predicate and follow this pattern:
>
> :- pred column_as_int(int::in, char::out) is det.
> column_as_int(Int, promise_only_solution(convert_int_to_char(Int))).
>
> :- pred convert_int_to_char(int::in, char::out) is cc_multi.
> convert_int_to_char(1, 'a').
> % ...
> convert_int_to_char(8, 'h').
> convert_int_to_char(_, '_').
>
> which, of course, it very hackish.
Yes. If you lie to the compiler like this,
it will undoubtably get its revenge eventually ;-)
> Is there a clean alternative to that?
:- func column_as_int(int) = char.
column_as_int(Int) = (if convert_int_to_char(Int, Char) then Char else '_').
:- pred convert_int_to_char(int::in, char::out) is semidet.
convert_int_to_char(1, 'a').
% ...
convert_int_to_char(8, 'h').
--
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