On Mon, Mar 10, 2003 at 09:49:47AM -0500, Tom Lane wrote:
> Hannu Krosing <hannu@tm.ee> writes:
> > Joe Conway kirjutas E, 10.03.2003 kell 05:35:
> >> CREATE OR REPLACE FUNCTION array_push (anyarray, anyscalar)
> >> RETURNS anyarray
> 
> > could you make it
> > RETURNS typeof($1)
> 
> Not directly --- we have to fit the return-type info into an OID field.
> We could fake it by inventing one or more pseudotypes, "SAMEASPARAMn".
> 
> But I think I like better the notion of extending my bound-together-
> ANYARRAY-and-ANYELEMENT proposal,
> http://archives.postgresql.org/pgsql-hackers/2003-03/msg00319.php
> 
> Suppose that we do that, and then further say that ANYARRAY or
> ANYELEMENT appearing as the return type implies that the return type
> is actually the common element or array type.  Then we have such
> useful behaviors as:
> 
> 	array_push(anyarray, anyelement) returns anyarray
> 	array_pop(anyarray) returns anyelement
> 	array_subscript(anyarray, int) yields anyelement
> 	singleton_array(anyelement) yields anyarray
> 
> The last three cases cannot be handled by a SAMEASPARAM construct.

... typeof($1)[], or a ARRAYELEMSAMEASPARAM construct?



I'm really liking this discussion.  I know this is sort of "out there", but
I have found in languages like StandardML and Objective CAML that templatized-
type functions are _extremely_ useful.   These languages type systems are
amazingly powerful (the language syntax is another matter *sigh*).

I'm not necessarily suggesting implementing this, but I just want to feed the
debate a bit.  I view the type system of these guys as "the ideal", and would
be in ecstacy if PostgreSQL had it, but I realize implementing the thing would
prolly be far from practical.

First, there are templatized types.  Arrays in PostgreSQL are sort of a 
kludge of templatized types, but they would be defined like so:

type a' array = <some definition ...>

which means that you are describing an array of some type a' (the apostrophe
indicates a type variable).

You can also create other neat templatized types as an aside:

type a' Nullable = Null | Value of a'

Which means the expressions:
 	Value 47 --> of type int Nullable
	Null --> of type a' Nullable (determined from context)

But then, you could also say:

	int array array

Or even:

	int Nullable array

Which is somthing you can't in PostgreSQL but would be very nice.  But then
you could say:

let invert_matrix m : a' array array -> a' array array = <code...>

let multiply x : a', y : a' -> a' = <code ...>

You could have more than one type variable in a templatized type or function,
true, but I've never really needed more than one.  I can imagine cases where
it would be useful, but just haven't needed one.

Plus:
	* get rid of horrible 'int4_' type hacks for array.
Minus:
	* can't use oid to represent exact type, rather a string of oids.
	* need second table to hold function type constraints when function
	  is templatized.  (or could make it params "oid array array", aka
	  oid[][]!) Reserve eight or ten oids for template parameter slots
	  (in other words, for a' through j' or something).

Warning: I have been called the "type nazi" <g>

One other thing from StandardML that I have always wanted in PostgreSQL
(or anywhere else I program, for that matter)- record types. (Warning, this is
also very wishful thinking and "out there").

In ML/CAML, a record type is defined like so:

type myrecord = {
	x : int,
	y : int,
	s : string
	};

"myrecord" is actually just type alias, the canonical record definition is:

	{s:string, x:int, y:int}

... with the attributes in alphabetical order, because unless you are mucking
with pointers in C, it really doesn't matter what order they are in.  The
first advantage become very apparent:  Any two records with the same named
attributes of the same types are always of the same type.  In PostgreSQL,
this would mean that functions that operate on RECORD{x:int,y:int,s:string}
could operate on a record from any relation with those attributes.

Further, to make inheritance pretty much unnecesary, you could allow a
record with more attributes to satisfy a parameter or return value constraint.
In other words, you could call function foo(RECORD{x:int,y:int}) on a
RECORD{s:string,x:int,y:int}.

I've thought about this trick a lot.  In theory there is a possibility of
not getting what you want, but in practice it would almost never happen.  The
demostrative case would be calling distance_from_origin(RECORD{x:int,y:int})
on RECORD{x:int,y:int,z:int}, but in this case you need to make a 
distance_from_origin(RECORD{x:int,y:int,z:int}).

This way, you could make a function which operates on RECORD{oid:oid} which
could be called on any record from a table.  I've wanted to do this sort of
thing on several occasions- one application has notes which can be attached
to any row, sort of like PostgreSQL comments.  Another to keep track of what
user changed which fields.  Etc.

Alright.... heheh I didn't mean to ramble.  /ME gets head out of clouds
and goes back to practical work <g>

>
> 			regards, tom lane
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordo0mo@postgresql.org

Mon, 10 Mar 2003 12:04:06 -0500
"Jason M. Felice" <jfelice@cronosys.com>
Re: SQL99 ARRAY support proposal