[mercury-users] "some" and existential types

Ralph Becket rbeck at microsoft.com
Sun Oct 3 02:40:53 AEST 1999



> Right, thanks! That appears to be the concept I was having trouble
> wrapping my head around, I couldn't see the difference between the two
> types of polymorphism. Just to shift focus for a second to 
> the caller, how
> exactly do you demand a particular return type?

Glad to be of assistance.  With existential types, the caller can't place
*any* constraints on what the type of the returned object is going to be -
that's up to the callee.  At best the callee will tell you that the returned
object belongs to one or more particular typeclasses.

> Would this work:
> 
> % no references to "X" before this point...
> 
> 	give_me_a_value(X),
> 	(
> 		X = [],
> 		...
> 	;
> 		X = [A|As],
> 		...
> 	),

This wouldn't work in the sense I think you mean, where

:- some [T] pred give_me_a_value(T).			% Case I

since in this case the *caller* has imposed the type constraint X:list(T)
whereas the callee has made no such promise.  However, if we had

:- some [T] pred give_me_a_value(list(T)).		% Case II

then your code would be fine, it's just that you wouldn't be able to decide
ahead of time what the type of A is going to be.

There are some subtleties here.  In case II, give_me_a_value/1 is going to
return a list of objects, of some type T which you the caller can't work
out, *all* of which will be of type T.  So, if T turns out to be an int then
you'll get a list(int) back - but the fact that they're ints won't be
visible
to you (unless you try something using e.g. type_of/1, but that's a whole
other can of worms).  If I have

:- type anything ---> some [T] thing(T).

:- pred give_me_a_value(list(anything)).

then what I get back is a list of anythings, each of which can encapsulate
an object of a completely different type to all the others.  In this
situation
you really want to use a typeclass constraint so that you can actually *do*
something with these objects.  For example,

:- type anything ---> some [T] thing(T) => printable(T).

means you can do things like

foo :-
	give_me_a_value(Xs),
	print_anythings(Xs).

print_anythings([]) --> [].
print_anythings([thing(X) | Xs]) --> print(X), print_anythings(Xs).

The things in the list can all be different, but because of the typeclass
constraint give_me_a_value/1 promises that they will all have a print//1
method defined for them.

QUESTION FOR THE MERCURY SQUAD: can I write something like the following,

print_anythings(Xs) --> list__foldl(print, Xs).

I suspect not, because the print//1 method may be different in each case.
However, to disallow this sort of code would be a great shame, IMHO.  Not
sure what the solution is, assuming this is the case.



> 
> If give_me_a_value is declared for some [T], then attempting 
> to constrain
> it to a list would create semidet code that would not 
> necessarily succeed?

That's correct.

> Indeed, a very very informative post, thank you kindly! It 
> occurs to me
> that you've practically written a new chapter for your tutorial in
> replying, perhaps worth putting on the web so you can just refer the
> desperately unenlightened to an appropriate url? :)

Good plan - I really ought to get back to work on that...  Tragically
I scored zero in the completer-finisher category on the psychometric
test I took!

Cheers,

Ralph
--------------------------------------------------------------------------
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