[m-dev.] for review: support constructions for existential data types

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Jul 8 05:50:43 AEST 1999


DJ, could you please review this one?

This change implements support for construction of existentially typed
data types, using what was originally I think DJ's suggestion:
adding some special syntax to distinguish constructions from
deconstructions.

DJ and I have talked about more ambitious proposals where this special
syntax would not be required.  However, those proposals are more complicated
and significantly more difficult to implement, so for the time being at
least I think we should stick with this simpler approach.

------------------------------

Estimated hours taken: 5

Allow construction unifications for existentially typed functors,
using the syntax "X = 'new foo'(Y)" rather than the usual "X = foo(Y)".
We need to use a special syntax for exisentially typed constructions
because type analysis and polymorphism need to know which occurrences
of existentially typed functors are constructors and which are deconstructors.

Note that we still don't yet support RTTI for existentially typed data types.

compiler/typecheck.m:
	For existentially typed functors, allow the functor to have
	a "new " prefix, and if so, make the quantifiers and constraints
	universal rather than existential.

compiler/polymorphism.m:
	For unifications with existentially typed functors,
	check for a "new " prefix on the functor.
	If the functor has such a prefix, strip off the prefix,
	and treat the unification as a construction rather than
	treating it as a deconstruction.

compiler/modecheck_unify.m:
	For construction unifications, check that all the type_info
	and typeclass_info arguments introduced by polymorphism.m
	are ground.

tests/hard_coded/typeclasses/existential_data_types.m:
	Change the test case to use this new feature,
	rather than hacking it using the C interface.

doc/reference_manual.texi:
	Document the new features.

Workspace: /home/mercury0/fjh/mercury
Index: compiler/modecheck_unify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modecheck_unify.m,v
retrieving revision 1.38
diff -u -r1.38 modecheck_unify.m
--- modecheck_unify.m	1999/06/30 17:12:33	1.38
+++ modecheck_unify.m	1999/07/07 17:00:45
@@ -487,7 +487,7 @@
 		),
 		mode_info_get_var_types(ModeInfo1, VarTypes),
 		categorize_unify_var_functor(ModeOfX, ModeOfXArgs, ModeArgs,
-				X, ConsId, ArgVars0, VarTypes,
+				X, ConsId, ArgVars0, VarTypes, UnifyContext,
 				Unification0, ModeInfo1,
 				Unification1, ModeInfo2),
 		split_complicated_subunifies(Unification1, ArgVars0,
@@ -1038,13 +1038,13 @@
 % be deterministic or semideterministic.
 
 :- pred categorize_unify_var_functor(mode, list(mode), list(mode), prog_var,
-		cons_id, list(prog_var), map(prog_var, type),
+		cons_id, list(prog_var), map(prog_var, type), unify_context,
 		unification, mode_info, unification, mode_info).
-:- mode categorize_unify_var_functor(in, in, in, in, in, in, in, in,
+:- mode categorize_unify_var_functor(in, in, in, in, in, in, in, in, in,
 			mode_info_di, out, mode_info_uo) is det.
 
 categorize_unify_var_functor(ModeOfX, ModeOfXArgs, ArgModes0,
-		X, NewConsId, ArgVars, VarTypes,
+		X, NewConsId, ArgVars, VarTypes, UnifyContext,
 		Unification0, ModeInfo0, Unification, ModeInfo) :-
 	mode_info_get_module_info(ModeInfo0, ModuleInfo),
 	map__lookup(VarTypes, X, TypeOfX),
@@ -1061,8 +1061,14 @@
 	(
 		mode_is_output(ModuleInfo, ModeOfX)
 	->
+		% It's a construction.
 		Unification = construct(X, ConsId, ArgVars, ArgModes),
-		ModeInfo = ModeInfo0
+
+		% For existentially quantified data types,
+		% check that any type_info or type_class_info variables in the
+		% construction are ground.
+		check_type_info_args_are_ground(ArgVars, VarTypes,
+			UnifyContext, ModeInfo0, ModeInfo)
 	;
 		% It's a deconstruction.
 		(
@@ -1109,6 +1115,30 @@
 			)
 		),
 		Unification = deconstruct(X, ConsId, ArgVars, ArgModes, CanFail)
+	).
+
+	% Check that any type_info or type_class_info variables
+	% in the argument list are ground.
+:- pred check_type_info_args_are_ground(list(prog_var), map(prog_var, type),
+		unify_context, mode_info, mode_info).
+:- mode check_type_info_args_are_ground(in, in, in,
+		mode_info_di, mode_info_uo) is det.
+
+check_type_info_args_are_ground([], _VarTypes, _UnifyContext) --> [].
+check_type_info_args_are_ground([ArgVar | ArgVars], VarTypes, UnifyContext)
+		-->
+	( 
+		{ map__lookup(VarTypes, ArgVar, ArgType) },
+		{ is_introduced_type_info_type(ArgType) }
+	->
+		mode_info_set_call_context(unify(UnifyContext)),
+		{ InitialArgNum = 0 },
+		modecheck_var_has_inst_list([ArgVar], [ground(shared, no)],
+			InitialArgNum),
+		check_type_info_args_are_ground(ArgVars, VarTypes,
+			UnifyContext)
+	;
+		[]
 	).
 
 %-----------------------------------------------------------------------------%
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.164
diff -u -r1.164 polymorphism.m
--- polymorphism.m	1999/06/30 17:12:36	1.164
+++ polymorphism.m	1999/07/07 17:22:59
@@ -1363,8 +1363,28 @@
 		% is this a construction or deconstruction of an
 		% existentially typed data type?
 		%
-		ConsId0 = cons(_, _),
-		type_util__get_existq_cons_defn(ModuleInfo0, TypeOfX, ConsId0,
+
+		%
+		% Check whether the functor had a "new " prefix.
+		% If so, assume it is a construction, and strip off the prefix.
+		% Otherwise, assume it is a deconstruction.
+		%
+		ConsId0 = cons(Functor0, Arity),
+		(
+			remove_new_prefix(Functor0, OrigFunctor)
+		->
+			ConsId = cons(OrigFunctor, Arity),
+			IsConstruction = yes
+		;
+			ConsId = ConsId0,
+			IsConstruction = no
+		),
+
+		%
+		% Check whether the functor (with the "new " prefix removed)
+		% is an existentially typed functor.
+		%
+		type_util__get_existq_cons_defn(ModuleInfo0, TypeOfX, ConsId,
 			ConsDefn)
 	->
 		%
@@ -1374,10 +1394,10 @@
 		map__apply_to_list(ArgVars0, VarTypes0, ActualArgTypes),
 		goal_info_get_context(GoalInfo0, Context),
 		polymorphism__process_existq_unify_functor(ConsDefn,
-			ActualArgTypes, TypeOfX, Context,
+			IsConstruction, ActualArgTypes, TypeOfX, Context,
 			ExtraVars, ExtraGoals, PolyInfo0, PolyInfo),
 		list__append(ExtraVars, ArgVars0, ArgVars),
-		Unify = unify(X0, functor(ConsId0, ArgVars), Mode0,
+		Unify = unify(X0, functor(ConsId, ArgVars), Mode0,
 				Unification0, UnifyContext) - GoalInfo0,
 		list__append(ExtraGoals, [Unify], GoalList),
 		conj_list_to_goal(GoalList, GoalInfo0, Goal)
@@ -1493,13 +1513,13 @@
 % an existentially quantified data constructor.
 %
 :- pred polymorphism__process_existq_unify_functor(
-		ctor_defn, list(type), (type), prog_context,
+		ctor_defn, bool, list(type), (type), prog_context,
 		list(prog_var), list(hlds_goal), poly_info, poly_info).
-:- mode polymorphism__process_existq_unify_functor(in, in, in, in,
+:- mode polymorphism__process_existq_unify_functor(in, in, in, in, in,
 		out, out, in, out) is det.
 
-polymorphism__process_existq_unify_functor(
-		CtorDefn, ActualArgTypes, ActualRetType, Context,
+polymorphism__process_existq_unify_functor(CtorDefn, IsConstruction,
+		ActualArgTypes, ActualRetType, Context,
 		ExtraVars, ExtraGoals, PolyInfo0, PolyInfo) :-
 
 	CtorDefn = ctor_defn(CtorTypeVarSet, ExistQVars0,
@@ -1543,19 +1563,22 @@
 	% type class constraints
 	%
 	
-	% assume it's a deconstruction
-	polymorphism__make_typeclass_info_head_vars(	
-			ExistentialConstraints, 
-			ExtraTypeClassVars,
-			PolyInfo1, PolyInfo2),
-	ExtraTypeClassGoals = [],
-/*******
-	% assume it's a construction
-	polymorphism__make_typeclass_info_vars(	
-			ExistentialConstraints, [], Context,
-			ExtraTypeClassVars, ExtraTypeClassGoals,
-			PolyInfo1, PolyInfo2),
-*******/
+	(
+		IsConstruction = yes,
+		% assume it's a construction
+		polymorphism__make_typeclass_info_vars(	
+				ExistentialConstraints, [], Context,
+				ExtraTypeClassVars, ExtraTypeClassGoals,
+				PolyInfo1, PolyInfo2)
+	;
+		IsConstruction = no,
+		% assume it's a deconstruction
+		polymorphism__make_typeclass_info_head_vars(	
+				ExistentialConstraints, 
+				ExtraTypeClassVars,
+				PolyInfo1, PolyInfo2),
+		ExtraTypeClassGoals = []
+	),
 
 	polymorphism__update_typeclass_infos(
 			ExistentialConstraints, ExtraTypeClassVars,
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.259
diff -u -r1.259 typecheck.m
--- typecheck.m	1999/06/30 17:12:42	1.259
+++ typecheck.m	1999/07/07 17:06:20
@@ -3168,6 +3168,41 @@
 	;
 		ConsInfoList0 = []
 	),
+
+	% For "existentially typed" functors, whether the functors
+	% is actually existentially typed depends on whether it is
+	% used as a constructor or as a deconstructor.  As a constructor,
+	% it is universally typed, but as a deconstructor, it is
+	% existentially typed.  But type checking and polymorphism need
+	% to know whether it is universally or existentially quantified
+	% _before_ mode analysis has inferred the mode of the unification.
+	% Therefore, we use a special syntax for construction unifications
+	% with existentially quantified functors: instead of just using the
+	% functor name (e.g. "Y = foo(X)", the programmer must use the
+	% special functor name "new foo" (e.g. "Y = 'new foo'(X)").
+	% 
+	% Here we check for occurrences of functor names starting with
+	% "new ".  For these, we look up the original functor in the
+	% constructor symbol table, and for any occurrences of that
+	% functor we flip the quantifiers on the type definition
+	% (i.e. convert the existential quantifiers and constraints
+	% into universal ones).
+	(
+		Functor = cons(Name, Arity),
+		remove_new_prefix(Name, OrigName),
+		OrigFunctor = cons(OrigName, Arity),
+		map__search(Ctors, OrigFunctor, HLDS_ExistQConsDefnList)
+	->
+		convert_cons_defn_list(TypeCheckInfo, HLDS_ExistQConsDefnList,
+			ExistQuantifiedConsInfoList),
+		list__filter_map(flip_quantifiers, ExistQuantifiedConsInfoList,
+			UnivQuantifiedConsInfoList),
+		list__append(UnivQuantifiedConsInfoList,
+			ConsInfoList0, ConsInfoList1)
+	;
+		ConsInfoList1 = ConsInfoList0
+	),
+
 	% Check if Functor is a constant of one of the builtin atomic
 	% types (string, float, int, character).  If so, insert
 	% the resulting cons_type_info at the start of the list.
@@ -3181,10 +3216,11 @@
 		varset__init(ConsTypeVarSet),
 		ConsInfo = cons_type_info(ConsTypeVarSet, [], ConsType, [],
 			constraints([], [])),
-		ConsInfoList1 = [ConsInfo | ConsInfoList0]
+		ConsInfoList2 = [ConsInfo | ConsInfoList1]
 	;
-		ConsInfoList1 = ConsInfoList0
+		ConsInfoList2 = ConsInfoList1
 	),
+
 	% Check if Functor is the name of a predicate which takes at least
 	% Arity arguments.  If so, insert the resulting cons_type_info
 	% at the start of the list.
@@ -3192,10 +3228,30 @@
 		builtin_pred_type(TypeCheckInfo, Functor, Arity,
 			PredConsInfoList)
 	->
-		list__append(ConsInfoList1, PredConsInfoList, ConsInfoList)
+		list__append(ConsInfoList2, PredConsInfoList, ConsInfoList)
 	;
-		ConsInfoList = ConsInfoList1
+		ConsInfoList = ConsInfoList2
 	).
+
+:- pred flip_quantifiers(cons_type_info, cons_type_info).
+:- mode flip_quantifiers(in, out) is semidet.
+
+flip_quantifiers(cons_type_info(A, ExistQVars0, C, D, Constraints0),
+		cons_type_info(A, ExistQVars, C, D, Constraints)) :-
+	% Fail if there are no existentially quantifier variables.
+	% We do this because we want to allow the 'new foo' syntax only 
+	% for existentially typed functors, not for ordinary functors.
+	% 
+	ExistQVars0 \= [],
+
+	% convert the existentially quantified type vars into
+	% universally quantified type vars by just discarding
+	% the old list of existentially quantified type vars and
+	% replacing it with an empty list.
+	ExistQVars = [],
+
+	% convert the existential constraints into universal constraints
+	dual_constraints(Constraints0, Constraints).
 
 %-----------------------------------------------------------------------------%
 
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.140
diff -u -r1.140 reference_manual.texi
--- reference_manual.texi	1999/06/30 17:13:18	1.140
+++ reference_manual.texi	1999/07/07 19:33:29
@@ -919,13 +919,21 @@
 the arguments of the functor must be distinct type variables.
 The @var{body} term is defined as
 a sequence of constructor definitions separated by semi-colons.
-Each constructor definition is a functor whose arguments (if any) are types.
-Type definitions must be @dfn{transparent}:
-all type variables occurring in the @var{body}
-must also occur in the @var{type}.
 
-Here are some examples:
+Ordinarily, each constructor definition must be a functor whose arguments
+(if any) are types.  Ordinary discriminated union definitions must be
+ at dfn{transparent}: all type variables occurring in the @var{body} must
+also occur in the @var{type}.  
+
+However, constructor definitions can optionally be existentially typed.
+In that case, the functor will be preceded by an existential type
+quantifier and can optionally be followed by an existential type
+class constraint.  For details, see @ref{Existential types}.
+Existentially typed discriminated union definitions need not be
+transparent.
 
+Here are some examples of discriminated union definitions:
+
 @example
 :- type fruit
         --->    apple
@@ -992,8 +1000,7 @@
         == list(pair(KeyType, ValueType)).
 @end example
 
-Like discriminated union type definitions,
-equivalence type definitions must be transparent.
+Equivalence type definitions must be transparent.
 Unlike discriminated union type definitions,
 equivalence type definitions must not be cyclic;
 that is, the type on the left hand side of the @samp{==}
@@ -3247,22 +3254,29 @@
 base classes in C++.
 
 Mercury supports existential type quantifiers on predicate and function
-declarations.  Unfortunately we do not yet support existential type
-quantifiers on data type definitions.  However, we do provide some
-work-arounds for this.
+declarations, and in data type definitions.  You can put type class
+constraints on existentially quantified type variables.
 
 @menu
+* Existentially typed predicates and functions::
+* Existential class constraints::
+* Existentially typed data types::
+* Some idioms using existentially quantified types::
+* Known bugs in the current implementation::
+ at end menu
+
+ at node Existentially typed predicates and functions
+ at section Existentially typed predicates and functions
+
+ at menu
 * Syntax for explicit type qualifiers::
 * Semantics of type qualifiers::
 * Examples of correct code using type quantifiers::
 * Examples of incorrect code using type quantifiers::
-* Existential class constraints::
-* Some idioms using existentially quantified types::
-* Known bugs in the current implementation::
 @end menu
 
 @node Syntax for explicit type qualifiers
- at section Syntax for explicit type qualifiers
+ at subsection Syntax for explicit type qualifiers
 
 Type variables in type declarations for polymorphic predicates or functions
 are normally universally quantified.  
@@ -3299,7 +3313,7 @@
 @end example
 
 @node Semantics of type qualifiers
- at section Semantics of type qualifiers
+ at subsection Semantics of type qualifiers
 
 If a type variable in the type declaration for a polymorphic predicate
 or function is universally quantified, this means the caller will
@@ -3341,7 +3355,7 @@
 elements of conjunctions in order to satisfy the modes.
 
 @node Examples of correct code using type quantifiers
- at section Examples of correct code using type quantifiers
+ at subsection Examples of correct code using type quantifiers
 
 Here are some examples of type-correct code using universal and
 existential types.
@@ -3389,7 +3403,7 @@
 @end example
 
 @node Examples of incorrect code using type quantifiers
- at section Examples of incorrect code using type quantifiers
+ at subsection Examples of incorrect code using type quantifiers
 
 Here are some examples of code using universal and
 existential types that contains type errors.
@@ -3461,62 +3475,174 @@
 versa.  But even then, any exception to this rule would have to involve
 a rather obscure coding style, which we do not recommend.)
 
+ at node Existentially typed data types
+ at section Existentially typed data types
+
+Note: existentially typed data types are not yet fully supported.
+See @ref{Known bugs in the current implementation} for details.
+
+Type variables occurring in the body of a discriminated union type
+definition may be existentially quantified.  Constructor definitions
+within discriminated union type definitions may be preceded by
+an existential type quantifier and followed by one or more existential
+type class constraints.
+
+For example:
+
+ at example
+:- type list_of_any
+	---> nil_any
+	;    some [T] cons_any(T, list_of_any).
+
+:- typeclass showable(T) where [ func show(T) = string ].
+:- type list_of_showable
+	---> nil
+	;    some [T] (cons(T, list_of_any) => showable(T)).
+
+:- typeclass foo(T1, T2) where [ /* ... */ ].
+:- type bar(T)
+	---> f1
+	;    f2(T)
+	;    some [T]
+	     f4(T)
+	;    some [T1, T2]
+	     (f4(T1, T2, T) => showable(T1), showable(T2))
+	;    some [T1, T2]
+	     (f5(list(T1), T2) => fooable(T1, list(T2)))
+	.
+ at end example
+
+Construction and deconstruction of existentially quantified data types
+are inverses: when constructing a value of an existentially quantified
+data type, the ``existentially quantified'' functor acts for purposes
+of type checking like a universally quantified function: the caller
+will determine the value of the type variable.
+Conversely, for deconstruction the functor acts like an
+existentially quantified function: the caller must be defined so
+as to work for all types which are an instance of the declared type.
+
+In order to make this distinction clear to the compiler,
+whenever you want to construct a value using an existentially
+quantified functor, you must prepend @samp{new } onto the functor name.
+This tells the compiler to treat it as though it were universally
+quantified: the caller can bind that functor's existentially quantified
+type variables to any type which satisfies the declared type class
+constraints.  Conversely, any occurrence without the @samp{new } prefix
+must be a deconstruction, and is therefore existentially quantified:
+the caller must not bind the existentially quantified type variables,
+but the caller is allowed to depend on those type variables satisfing
+the declared type class constraints, if any.
+
+For example, the function @samp{make_list} constructs a value of type
+ at samp{list_of_showable} containing a sequence of values of different types,
+all of which are instances of the @samp{showable} class
+
+ at example
+:- instance showable(int).
+:- instance showable(float).
+:- instance showable(string).
+
+:- func make_list = list_of_showable.
+make_list = List :-
+	Int = 42,
+	Float = 1.0,
+	String = "blah",
+	List =  'new cons'(Int,
+		'new cons'(Float,
+		'new cons'(String, nil))).
+ at end example
+
+while the function @samp{process_list} below applies the @samp{show}
+method of the @samp{showable} class to the values in such a list.
+
+ at example
+:- func process_list(list_of_showable) = list(string).
+process_list(nil) = "".
+process_list(cons(Head, Tail)) = [show(Head) | process_list(Tail)].
+ at end example
+
 @node Some idioms using existentially quantified types
 @section Some idioms using existentially quantified types
 
-The standard library module @samp{std_util} provides a type
-named @samp{univ} which can hold values of any type. 
+The standard library module @samp{std_util} provides an abstract
+type named @samp{univ} which can hold values of any type. 
 You can form heterogenous containers (containers that can hold values of
 different types at the same time) by using data structures
 that contain @code{univ}s, e.g. @samp{list(univ)}.
+
+The interface to @samp{std_util} includes the following:
+
+ at example
+% `univ' is a type which can hold any value.
+:- type univ.
 
-	@example
-	% `univ' is a type which can hold any value.
-	:- type univ.
-
-	% The function univ/1 takes a value of any type and constructs
-	% a `univ' containing that value (the type will be stored along
-	% with the value)
-	:- func univ(T) = univ.
-
-	% The function univ_value/1 takes a `univ' argument and extracts
-	% the value contained in the `univ' (together with its type).
-	% This is the inverse of the function univ/1.
-	:- some [T] func univ_value(univ) = T.
-	@end example
+% The function univ/1 takes a value of any type and constructs
+% a `univ' containing that value (the type will be stored along
+% with the value)
+:- func univ(T) = univ.
 
+% The function univ_value/1 takes a `univ' argument and extracts
+% the value contained in the `univ' (together with its type).
+% This is the inverse of the function univ/1.
+:- some [T] func univ_value(univ) = T.
+ at end example
+
+The @samp{univ} type in the standard library is in fact a simple
+example of an existentially typed data type.  It could be implemented
+as follows:
+
+ at example
+:- implementation.
+:- type univ ---> some [T] mkuniv(T).
+univ(X) = 'new mkuniv'(X).
+univ_value(mkuniv(X)) = X.
+ at end example
+
 An existentially typed procedure is not allowed to have different
 types for its existentially typed arguments in different clauses or
 or in different subgoals of a single clause.  For instance, both
 of the following examples are illegal:
 
-	:- some [T] pred bad_example(string, T).
-	bad_example("foo", 42).
-	bad_example("bar", "blah").
-		% type error (cannot unify `int' and `string')
-
-	:- some [T] pred bad_example2(string, T).
-	bad_example2(Name, Value) :-
-		( Name = "bar", Value = 42
-		; Name = "bar", Value = "blah"
-		).
-		% type error (cannot unify `int' and `string')
+ at example
+:- some [T] pred bad_example(string, T).
+bad_example("foo", 42).
+bad_example("bar", "blah").
+	% type error (cannot unify `int' and `string')
+
+:- some [T] pred bad_example2(string, T).
+bad_example2(Name, Value) :-
+	( Name = "foo", Value = 42
+	; Name = "bar", Value = "blah"
+	).
+	% type error (cannot unify `int' and `string')
+ at end example
 
 However, using @samp{univ},
 it is possible for an existentially typed function to return
 values of different types at each invocation.
 
-	:- some [T] pred good_example(string, T).
-	good_example(Name, univ_value(Univ)) :-
-		( Name = "bar", Univ = univ(42)
-		; Name = "bar", Univ = univ("blah")
-		).
-
-Unfortunately this technique doesn't work if you also want to use
-type class constraints.  Eventually we hope to support existentially
-typed data types with type class constaints, which would address this issue.
- at c (In the mean time, as a work-around, it is in fact possible to achieve
- at c the same effect via some hacks using the C interface.)
+ at example
+:- some [T] pred good_example(string, T).
+good_example(Name, univ_value(Univ)) :-
+	( Name = "foo", Univ = univ(42)
+	; Name = "bar", Univ = univ("blah")
+	).
+ at end example
+
+Using @samp{univ} doesn't work if you also want to use type class constraints.  
+If you want to use type class constraints, then you must define your own
+existentially typed data type, analagous to @samp{univ}, and use that:
+
+ at example
+:- type univ_showable ---> some [T] (mkshowable(T) => showable(T)).
+
+:- some [T] pred harder_example(string, T) => showable(T).
+harder_example(Name, Showable) :-
+	( Name = "bar", Univ = 'new mkshowable'(42)
+	; Name = "bar", Univ = 'new mkshowable'("blah")
+	),
+	Univ = mkshowable(Showable).
+ at end example
 
 @node Known bugs in the current implementation
 @section Known bugs in the current implementation
@@ -3527,6 +3653,14 @@
 The symptom in such cases is spurious mode errors.
 The solution is to write such code in the correct order manually
 rather than relying on the compiler's mode reordering.
+
+We have not yet implemented RTTI (run-time type information) support
+for existentially quantified data types.  This means that many of
+the procedures in the Mercury standard library will not work for
+values of those types.  Functions affected include for example
+ at samp{io__write}, @samp{io__read}, @samp{std_util__construct},
+and @samp{std_util__deconstruct}.  Likewise, the Mercury debugger
+does not yet support such types.
 
 @node Semantics
 @chapter Semantics
Index: tests/hard_coded/typeclasses/existential_data_types.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/typeclasses/existential_data_types.m,v
retrieving revision 1.2
diff -u -r1.2 existential_data_types.m
--- existential_data_types.m	1999/06/30 17:13:38	1.2
+++ existential_data_types.m	1999/07/07 17:14:53
@@ -67,15 +67,4 @@
 
 my_univ_value(make_my_univ(X)) = X.
 
-/*
-** Construction of existentially typed data types are not yet implemented,
-** so we have to use the C interface.
-*/
-% my_univ(X) = make_my_univ(X).
-:- pragma c_code(my_univ(Value::in) = (Univ::out), will_not_call_mercury, "
-        incr_hp(Univ, 2);
-        field(mktag(0), Univ, 0) = (Word)
-                TypeClassInfo_for_existential_data_types__fooable_T;
-        field(mktag(0), Univ, 1) = (Word) Value;
-
-").
+my_univ(X) = 'new make_my_univ'(X).

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list