Browse thread
fixed length arrays as types
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | Brian Rogoff <bpr@b...> |
| Subject: | Re: fixed length arrays as types |
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 <int unsigned N> 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