Определение типа массива с заданным количеством элементов - PullRequest
3 голосов
/ 18 мая 2019

Я хочу создать массив, который может содержать не более и не менее трех элементов. Есть ли способ сделать это в определении типа?

Ответы [ 3 ]

6 голосов
/ 18 мая 2019

Нет, это больше не будет массивом. Однако вы можете создать кортеж из трех элементов:

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

Кортеж также может иметь элементы разных типов и может быть непосредственно деструктурирован вместо сопоставления с образцом, поскольку его точная форма известна во время компиляции:

let (a, b, c): int * float * string = (1, 2.7, "3")
3 голосов
/ 18 мая 2019

Да, вы можете:

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|]

Теперь гарантируется, что каждый раз, когда вы видите значение типа Array3, оно содержит ровно три элемента:

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

Подробнее об этой технике вы можете прочитать в этой книге .

2 голосов
/ 18 мая 2019

Опираясь на ответы @Nghia Bui и @glennsl, вы можете определить свой собственный тип Triple, используя кортеж из трех элементов для безопасности типов:

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)

Или вы можете сделатьэто универсально:

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