From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from weis@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id SAA20588 for caml-red; Wed, 8 Nov 2000 18:21:42 +0100 (MET) Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id SAA31791 for ; Tue, 7 Nov 2000 18:00:19 +0100 (MET) Received: from shell5.ba.best.com (shell5.ba.best.com [206.184.139.136]) by concorde.inria.fr (8.11.1/8.10.0) with ESMTP id eA7H0Fb18481 for ; Tue, 7 Nov 2000 18:00:18 +0100 (MET) Received: from localhost (bpr@localhost) by shell5.ba.best.com (8.9.3/8.9.2/best.sh) with ESMTP id JAA06374; Tue, 7 Nov 2000 09:00:13 -0800 (PST) Date: Tue, 7 Nov 2000 09:00:13 -0800 (PST) From: Brian Rogoff To: Chris Hecker cc: caml-list@inria.fr Subject: Re: fixed length arrays as types In-Reply-To: <4.3.2.7.2.20001104165041.00b3e370@shell16.ba.best.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: weis@pauillac.inria.fr On Sat, 4 Nov 2000, Chris Hecker wrote: > Is there any way to do this: > > type vector3 = [| float; float; float |]; > > Basically, I want an array of a given length to be a given type, so I > can use the type system to check add_vector3 rather than throwing if the > arrays don't match. I know I can make records {x:float, y:float} but > I'd like it to be parameterizable at compile time. Use the module system to create an ADT which hides the implementation of the type as an array. If you wish the ADT to be parameterized by a value, as in C++ templates or Ada generic packages, then you'd use a functor to generate the particular module you wish for. As always, the downside of hiding representation is that you lose pattern matching on the ADT. > Something like this C++: > > template class vector { float a[N]; }; > vector<3> add( vector<3> v1, vector<3> v2 ); > > vector<3> v3 = add(vector<3>(),vector<3>()); // works > vector<3> v4 = add(vector<5>(),vector<3>()); // type error (note v<5> Here's a sketch in Ocaml. You'll have to decide how you want to do "add", if you want to parameterize by array element type and all that module type FixedLengthArrayType = sig type elem type t val make : elem -> t val get : t -> int -> elem val set : t -> int -> elem -> unit val of_array : elem array -> t val to_array : t -> elem array end;; module type ArrayParamsType = sig type t val initial_value : t val length : int end;; module FixedLengthArray(Params : ArrayParamsType) : (FixedLengthArrayType with type elem = Params.t)= struct type elem = Params.t type t = elem array let make v = Array.make Params.length v let get fla i = Array.get fla i let set fla i v = Array.set fla i v let (of_array : elem array -> t) = fun a -> let _ = assert(Array.length a = Params.length) in a let (to_array : t -> elem array) = fun fla -> fla end;; module Arr3 = FixedLengthArray(struct type t = float let initial_value = 0.0 let length = 4 end);; etc. All that was much more verbose than it needed to be but I hope it was clear. > I guess the higher level question is whether scalar constants can be > part of the type signature like they can be in C++. Or, the related but > different question is whether there's a way to differentiate between > "float a[]" (or "float *a"), the variable length array type, and "float > a[3]", a fixed length array type, which C++ doesn't do, but it lets you > wrap the ideas in template classes which do allow you to represent this > to the type system. It's a bit different in ML (Ocaml and SML) in that you use the module system to handle parameterization by values. -- Brian