Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array of a type with a parameter in Ocaml

I have a homework exercise to do in Ocaml...

My teacher said that we must use these 2 types:

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

My problem is that when I create an array:

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

I don't know what values can be inserted in this array...

a.(0)<-???

Can someone tell me which value can be inserted in this array?

like image 472
Cevap Avatar asked Jun 01 '11 08:06

Cevap


2 Answers

Until you add anything to the array the type is not fully defined. This is reflected in the type indicated for the array:

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

If you look closely you will see that the 'a you gave as type parameter has become a '_a (note the _). This type means "some type, but I do not know which one yet". As opposed to 'a which means any type.

This means at this point you can insert any kind of Zapis. Once you do that, you can only insert Zapis of that special type (in further types the '_a goes away and is replaced with the correct type).

So if you do

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

a will become a int zapis array and only accept ints from that moment on.

if you do instead

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

it will become a string zapis array only accept strings afterwards.

like image 180
LiKao Avatar answered Sep 28 '22 09:09

LiKao


Can you tell me how to create an array type asocpolje?

'a asocpolje and 'a zapis array are the same type. Depending on how exactly the typer infer your definitions, you will get one or the other, but they're exactly equivalent. 'a asocpolje is just an alias for 'a zapis array, not a new type.

You can help OCaml print the right type information by using an explicit type annotation :

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

I would however discourage this practice. It behaves in non-obvious ways (eg. the meaning of 'a here may be surprising, it does not enforce polymorphism) and you're really trying to make a difference where there isn't (the types are the same). If you really want a distinction between both types, you should define 'a asocpolje as a new algebraic type (with only one case):

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)
like image 45
gasche Avatar answered Sep 28 '22 09:09

gasche