TD 1 : Introduction à la programmation OCaml

 Login :  Mot de passe :

\[ \DeclareMathOperator{\even}{even} \DeclareMathOperator{\odd}{odd} \DeclareMathOperator{\true}{true} \DeclareMathOperator{\false}{false} \]

En salle machine, nous vous recommandons d’utiliser Eclipse configuré avec le plugin OCaml. Pour cela, commencez par démarrer Eclipse. Pourq installer le plugin OCaml, allez dans le menu Help -> Install New Software… Une boîte de dialogue apparaîtra. À partir de cette dernière, ajoutez une nouvelle source de plugin en cliquant sur le bouton Add... (dans la section Work with...). Le nom de la source (champ Name de la nouvelle boîte de dialogue) importe peu — utilisez OCaml par example. La source (champ Location) doit être positionné sur

Validez la nouvelle source. Dans la liste sous la section Work with..., le plugin OcaIDE devrait apparaître. Sélectionnez le puis validez. Eclipse vous demandera de confirmer l’installation de OcaIDE et d’accepter sa licence. Une fois l’installation terminée, Eclipse vous proposera de redémarrer. Acceptez.

(Nous fournissons également des instructions pour installer un environnement de développement pour OCaml chez vous).

Jouons avec le top-level OCaml

Pour cette session, nous vous recommandons d’utiliser un top-level graphique comme celui de OcaIDE ou ocaml-top. Ouvrez votre top-level OCaml. Vous verrez alors apparaître une invite de commandes telle que:

        OCaml version 4.03.0
  
#

À partir de là, il vous est possible d’entrer des expressions OCaml qui seront interprétées au fil de l’eau par le top-level – ces expressions doivent se terminer par un ;; afin d’indiquer que vous avez fini votre saisie. E.g., taper la commande 42;; puis appuyez sur entrée. Le top-level évalue l’expression, puis imprime le résultat accompagné du type de l’expression :

# 42 ;;
- : int = 42
# 

Vous pouvez aussi essayer avec 21+21 :

# 21 + 21 ;;
- : int = 42

Notez que l’expression n’a pas à être saisie sur une seule ligne comme avec :

# 21 +
    21
  ;;
- : int = 42

D’où l’importance des ;; finaux ! (Ces derniers disparaitront lorsque nous utiliserons OCaml comme compilateur et non plus comme interpréteur)

Il est également possible de définir des variables via l’instruction let, par exemple :

# let x = 3 ;;
- val x : int = 3

Ici, OCaml vous indique la création d’une variable x de type int et initialisée à 3. Cette variable peut ensuite être utilisée dans les expressions, comme dans :

# x + x ;;
- : int = 6

Notez que les variables en OCaml sont immuables : x vaut 3 et il n’est plus possible de changer sa valeur. Pas contre, vous pouvez redéfinir x :

# let x = 4 ;;
- val x : int = 4

Ici, nous définissons une nouvelle variable x mais cette fois ci initialisée à 4 et qui cache la première définition de x. La différence est subtile et nous reviendrons dessus plus tard lors d’exerices sur l’ordre supérieur et les clôtures.

De la même manière, la construction let nous permet de définir des fonctions :

# let f a = a * a
val f : int -> int = <fun>

Ici, f est une fonction (indiqué par le <fun>) de type int -> int (c’est-à-dire qui prend un argument de type int et renvoie une valeur de type int). Il est à noter que le type de f a été inféré. Optionnellement, il est possible d’indique le type des arguments ou du retour d’une fonction :

# let f (a : int) : int = a * a
val f  int -> int = <fun>

Le faire peut parfois aider à comprendre une erreur de typage (due à une erreur de programmation) en guidant l’inférence de type – notamment lors du typage de fonctions récursives.

De même qui pour les variables, f peut ensuite être utilisée dans les expressions :

# f 2 + f x
- : int = 15

Notez que l’application en OCaml se fait par juxtaposition : il n’y a pas de parenthèses.

On peut bien sûr définir des fonctions à plusieurs arguments :

# let g a b = a + a * b
val g : int -> int -> int = <fun>

et le corps d’une fonction peut utiliser des fonctions ou des variables précédemment définies :

# let x = 3
val x : int = 3
# let f a = a * a
val f : int -> int = <fun>
# let h a = f a + x
val h : int -> int = <fun>
# h 2
- : int = 7
# let x = 4
val x : int = 4
# h 2
- : int = 7

Notez que cet exemple montre bien qu’une variable est immuable. Redéfinir x ne change pas le comportement de h !

Expression OCaml / Typage

Donner le type des expressions suivantes (lorsque possible) :

Le nom du fichier à déposer
Il faut se connecter avant de pouvoir déposer

01)   42
02)   42.0
03)   42,0
04)   42;0
05)   true
06)   ()
07)   []
08)   [1]
09)   [1, true]
10)   [1; true]
11)   1 + 1
12)   1. + 1
13)   1. +. 0.
14)   x
15)   'x'
16)   "x"
17)   0 = 1

Typage

Donner des exemples d’expressions OCaml ayant les types suivants :

Le nom du fichier à déposer
Il faut se connecter avant de pouvoir déposer

01)   int
02)   int * bool
03)   int -> bool
04)   int * int -> string

Let-bindings

Pour chacune des expressions ci-dessous, donner la valeur retournée par l’interpréteur OCaml.

Le nom du fichier à déposer
Il faut se connecter avant de pouvoir déposer

01)   let a = 1 in a + 2
02)   let a = 1 in a + 2; a
03)   (let a = 1 in a + 2); a
04)   let a = 7 in let b = a in a + b
05)   let a = 1 in let a = 2 in a
06)   let a = 1 in (let a = 2 in ()); a
07)   let f x = fun y -> x * y in let g = f 3 in g 5

Ordre supérieur / paramétricité

Le nom du fichier à déposer
Il faut se connecter avant de pouvoir déposer

Récursivité (simple, mutuelle, mémoisation & terminale)

Le nom du fichier à déposer
Il faut se connecter avant de pouvoir déposer

Listes (structure de données)

Le nom du fichier à déposer
Il faut se connecter avant de pouvoir déposer

Types record, types sommes

Le nom du fichier à déposer
Il faut se connecter avant de pouvoir déposer

Atout Non Atout
Valet : 20 points As : 11 points
9 : 14 points 10 : 10 points
As : 11 points Roi : 4 points
10 : 10 points Dame : 3 points
Roi : 4 points Valet : 2 points
Dame : 3 points 9 : 0 points
8 : 0 points 8 : 0 points
7 : 0 points 7 : 0 points

Références, entrées/sorties

Le nom du fichier à déposer
Il faut se connecter avant de pouvoir déposer