Version française
Home     About     Download     Resources     Contact us    
Browse thread
fixed length arrays as types
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ 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