Version française
Home     About     Download     Resources     Contact us    
Browse thread
module, module type et foncteurs, ...
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Xavier Leroy <Xavier.Leroy@i...>
Subject: Re: module, module type et foncteurs, ...
> [Erreur mystérieuse avec des foncteurs:]
> Type declarations do not match:
>   type b = Make_B(A).b = | TA of A.a | TB of b
> is not included in
>   type b = | TA of A.a | TB of b

Le message d'erreur est justifié, mais difficile à comprendre car en
fait tu as deux modules différents qui s'appellent tous deux "A" avec
tous deux une composante de type "a",  et le typeur est juste en train
de te dire que les deux types "A.a" sont différents.

Reprenons:

> module A = struct
>   type a = A | B | C
>   let id (x : a) = x
> end

Ça, c'est ton premier module A.

> module type T_A = sig
>   type a
>   val id : a -> a
> end
> module type T_A_detail = sig
>   type a = A | B | C
> end
> module type T_A_choisi = T_A
> module type T_B = sig
>   type a
>   type b =
>     | TA of A.a
>     | TB of b
> end

Remarquons que T_B fait référence au premier module A.

> module type T_Make_B = functor (A : T_A_choisi) -> T_B

Là, tu introduis un second module A qui est le paramètre du foncteur,
mais l'occurrence de A.a dans T_B fait toujours référence au premier
module A.

> module Make_B (A : T_A_choisi) = struct
>   type a = A.a
>   type b =
>     | TA of A.a
>     | TB of b
> end

Par conséquent, Make_B n'a pas le type T_Make_B, mais plutôt

        functor (A : T_A_choisi) ->
          sig
            type a
            type b =
              | TA of A.a
              | TB of b
          end

où A.a fait maintenant référence au paramètre du foncteur.

> module Make_C (A : T_A_detail) (Make_B : T_Make_B) = struct
>   let string_of_a = function
>     | A.A -> "A"
>     | A.B -> "B"
>     | A.C -> "C"
> end
> module B2 = Make_B (A)
> module C2 = Make_C (A) (Make_B)

C'est normal que ça fasse une erreur puisque Make_B n'est pas du type
T_Make_B attendu par Make_C.

> Je ne comprend pas qu'elle est la difference entre 
>   type b = Make_B(A).b = | TA of A.a | TB of b
> et 
>   type b = | TA of A.a | TB of b

Le premier type contient plus d'infos que le second: on sait que non
seulement il a des constructeurs TA et TB avec les types indiqués,
mais que de plus il est compatible avec Make_B(A).b.  En temps normal
(si les deux occurrences de A.a sont bien le même type!), la première
déclaration est "sous-type" de la seconde, puisqu'on peut toujours
oublier l'info supplémentaire.

> D'un autre cote est-ce qu'un type de tableau de booleens qui serait
> represente de maniere efficace existe ? on aurrait un bit par
> booleen, et non un int comme cela est fait actuellement.  J'imagine
> qu'on peut faire cela en definissant un type de tableau d'entier, et
> aller voir la valeur de chaque bit de ces entiers.

Il n'y a pas (encore?) de module de bibliothèque qui fasse cela, mais
c'est en effet facile à implémenter.  Mieux vaut utiliser une chaîne
de caractères qu'un tableau d'entiers (31 ou 63 bits), cependant.

- Xavier Leroy