Массив типа с параметром в Ocaml - PullRequest
9 голосов
/ 01 июня 2011

У меня есть домашнее задание в Ocaml ...

Мой учитель сказал, что мы должны использовать эти 2 типа:

type 'a zapis = Prazen | Zapis of string * 'a;;
type 'a asocpolje = 'a zapis array;;

Моя проблема в том, что когда я создаю массив:

# let a = Array.make 5 Prazen;;
val a : '_a zapis array = [|Prazen; Prazen; Prazen; Prazen; Prazen|]

Я не знаю, какие значения можно вставить в этот массив ...

a.(0)<-???

Может кто-нибудь сказать мне, какое значение можно вставить в этот массив?

Ответы [ 2 ]

11 голосов
/ 01 июня 2011

Пока вы ничего не добавите в массив, тип не определен полностью. Это отражено в типе, указанном для массива:

val a : '_a zapis array = [|Prazen; Prazen; Prazen; Prazen; Prazen|]

Если вы посмотрите внимательно, то увидите, что 'a, который вы указали в качестве параметра типа, стал '_a (обратите внимание на _). Этот тип означает «некоторый тип, но я еще не знаю, какой». В отличие от 'a, что означает любой тип.

Это означает, что на данный момент вы можете вставить любой вид Zapis. Как только вы это сделаете, вы можете вставить Zapis только этого специального типа (в следующих типах '_a исчезает и заменяется на правильный тип).

Так что, если вы делаете

a.(0) <- Zapis ("z", 10)

a станет int zapis array и будет принимать только целые числа с этого момента.

если вы делаете вместо

a.(0) <- Zapis ("z","z") 

он станет string zapis array только после того, как принимает строки.

5 голосов
/ 01 июня 2011

Можете ли вы сказать мне, как создать массив типа asocpolje?

'a asocpolje и 'a zapis array являются одного типа . В зависимости от того, как именно типизатор выведет ваши определения, вы получите одно или другое, но они в точности эквивалентны. 'a asocpolje это просто псевдоним для 'a zapis array, а не новый тип.

Вы можете помочь OCaml напечатать правильную информацию о типе, используя явную аннотацию типа:

let t : 'a asocpolje = Array.make ...

Однако я бы не одобрил эту практику. Он ведет себя неочевидным образом (например, значение 'a здесь может быть удивительным, он не приводит к полиморфизму), и вы действительно пытаетесь изменить ситуацию там, где ее нет (типы одинаковы). Если вы действительно хотите провести различие между обоими типами, вы должны определить 'a asocpolje как новый алгебраический тип (только с одним регистром):

type 'a zapis = Prazen | Zapis of string * 'a;;
type 'a asocpolje = Asocpolje of 'a zapis array;;

let t = Asocpolje (Array.make ...)
let get (Asocpolje t) n = t.(n)
...