[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