3

I was wondering if it is possible to have compile-time check in OCaml to make sure arrays are the correct length. For my problem, I want to verify that two GPU 1-dim vectors are of the same length before doing piecewise vector subtraction.

let init_value = 1
let length = 10_000_000
let x = GpuVector.create length init_value and y = GpuVector.create 9 init_value in
let z = GpuVector.sub v1 v2

In this example I would like it to throw a compile error as x and y are not the same length. As I am a OCaml noob I would like to know how I can achieve this? I am guessing that I will have to use functors or camlp4 (which I have never used before)

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
user3199023
  • 433
  • 2
  • 8
  • OCaml itself has no dependent types, which can be used to check array length mismatch statically. One thing you can do is to use phantom types which carries a phantom encoding the array length. These encodings could be auto-generated from integer constants using CamlP4... But this is not dependent type and likely not enough for your purpose. – camlspotter Feb 21 '14 at 09:53
  • @camlspotter I just found your comment. Have a similar problem. Could you provide some hints/pointers on encoding natural numbers as types? – krokodil Feb 13 '18 at 06:45
  • @krokodil, now you can try slap, just as Pierre pointed out in his answer. – camlspotter Feb 15 '18 at 02:40

2 Answers2

5

You cannot define a type family in OCaml for arrays of length n where n can have arbitrary length. It is however possible to use other mechanisms to ensure that you only GpuVector.sub arrays of compatible lengths.

The easiest mechanism to implement is defining a special module for GpuVector of length 9, and you can generalise the 9 by using functors. Here is an example implementation of a module GpuVectorFixedLength:

module GpuVectorFixedLength =
struct
module type P =
sig
  val length : int
end

module type S =
sig
  type t
  val length : int
  val create : int -> t
  val sub : t -> t -> t
end

module Make(Parameter:P): S =
struct
  type t = GpuVector.t
  let length = Parameter.length
  let create x = GpuVector.create length x
  let sub = GpuVector.sub
end
end

You can use this by saying for instance

module GpuVectorHuge = GpuVectorFixedLength.Make(struct let length = 10_000_000 end)
module GpuVectorTiny = GpuVectorFixedLength.Make(struct let length = 9 end)
let x = GpuVectorHuge.create 1
let y = GpuVectorTiny.create 1

The definition of z is then rejected by the compiler:

let z = GpuVector.sub x y
                        ^
Error: This expression has type GpuVectorHuge.t
       but an expression was expected of type int array

We therefore successfully reflected in the type system the property for two arrays of having the same length. You can take advantage of module inclusion to quickly implement a complete GpuVectorFixedLength.Make functor.

Michaël Le Barbier
  • 6,103
  • 5
  • 28
  • 57
2

The slap library implements such kind of size static checks (for linear algebra). The overall approach is described this abstract

Pierre Chambart
  • 1,469
  • 12
  • 17
  • the link to the abstract seems defunct (404); do you know by chance where one can find it now? – akavel Nov 06 '16 at 14:25
  • 1
    This is not exactly the original abstract, but this is I think more complete http://eptcs.web.cse.unsw.edu.au/paper.cgi?ML2014.1.pdf – Pierre Chambart Nov 06 '16 at 16:56