Jamie Dixon
Jamie Dixon

Reputation: 4292

Defining an array type with a set number of elements

I want to create an array that can have no more and no less than three elements. Is there a way to do that in a type definition?

Upvotes: 3

Views: 85

Answers (3)

LSM07
LSM07

Reputation: 817

Building on both @Nghia Bui 's and @glennsl 's answers, you can define your own Triple type using a tuple of three elements for type safety:

type Triple = Triple of int * int * int 
    with
    static member inline (+) (t1, t2) =
        match t1, t2 with 
        | Triple (a1, a2, a3), Triple (b1, b2, b3) -> Triple (a1 + b1, a2 + b2, a3 + b3)
    //add other functionality like map, fold, etc you'd normally expect from Arrays  
let t1 = Triple (1, 2, 3)
let t2 = Triple (4, 5, 6)
t1 + t2 //val it : Triple = Triple (5,7,9)

Or you can make it generic:

type GenericTriple<'a> = GenericTriple of 'a * 'a * 'a
    with
    static member // etc...

Upvotes: 2

Nghia Bui
Nghia Bui

Reputation: 3784

Yes, you can:

type Array3<'T> = private Array3 of 'T [] with
    member this.Elements = let (Array3 xs) = this in xs
    static member Create x y z = Array3 [|x;y;z|]

Now it is ensured that everytime you see a value of type Array3, the value has exactly three elements:

let myArray = Array3.Create 1 2 3
myArray.Elements |> printfn "%A"

You can read more about this technique in this book.

Upvotes: 3

glennsl
glennsl

Reputation: 29106

No, that wouldn't really be an array any longer. You can however create a tuple of three elements:

let triple: int * int * int = (1, 2, 3)

A tuple can also have elements of different types and can be destructured directly instead of through pattern matching since its exact shape is known at compile-time:

let (a, b, c): int * float * string = (1, 2.7, "3")

Upvotes: 6

Related Questions