Functeurs à Ocaml
-
11-07-2019 - |
Question
J'ai un petit problème avec un foncteur (et le type qui en résulte). Ci-dessous, j'ai un foncteur Set qui utilise un type Ordered. En fait, j’ai utilisé le code set.ml
fourni avec ocaml à des fins d’aide, mais il semble que je fasse tout ce qu’il faut ahhem . J'ai créé un module Ordered avec des entiers et je l'ai appliqué au foncteur Set pour obtenir le dernier module de cet exemple de code, IntSet.
La ligne suivante échoue lorsque j'essaie d'insérer un entier. Je reçois le type d'erreur suivant:
Error: This expression has type int but is here used with type
SetInt.elt = Set(OrdInt).elt
Ne vous méprenez pas, le système de types est correct ici. Le niveau supérieur indique que le type de SetInt.elt
est Set (OrdInt) .elt
, mais lorsque je fais les mêmes opérations pour configurer un Set à l'aide de celui fourni. par ocaml, la même ligne est SetInt.elt = OrderedInt.t
. On dirait que je devrais recevoir SetInt.elt = Ordered.t
.
C’est si simple, il me manque probablement quelques détails stupides! argh!
Remarque: j'ai simplifié les fonctions membre / insertion ici car ce problème concerne les types.
module type Ordered =
sig
type t
val lt : t -> t -> bool
val eq : t -> t -> bool
val leq : t -> t -> bool
end
module type S =
sig
type elt
type t
exception Already_Exists
val empty : t
val insert : elt -> t -> t
val member : elt -> t -> bool
end
module Set (Elt:Ordered) : S =
struct
type elt = Elt.t
type t = Leaf | Node of t * elt * t
exception Already_Exists
let empty = Leaf
let insert e t = t
let member e t = false
end
module OrdInt : Ordered =
struct
type t = int
let lt a b = a < b
let eq a b = a = b
let leq a b = a <= b
end
module IntSet = Set (OrdInt)
(* line that fails *)
let one_elm = IntSet.insert 1 IntSet.empty
La solution
Vous devez changer ces deux lignes
module Set (Elt:Ordered) : S =
module OrdInt : Ordered =
à
module Set (Elt:Ordered) : S with type elt = Elt.t =
module OrdInt : Ordered with type t = int =
Sans cela, les modules n'auront pas de signatures exposant les types elt et t as int.
[Modifier]: Le fichier set.ml n'a pas le bit 'with', car il existe un sml.mli, qui déclare la signature du foncteur et qui possède le 'with'. De plus, OrdInt n'a pas besoin de 'avec' si vous ne spécifiez pas explicitement de signature, comme ceci:
module OrdInt =
Vous pouvez également construire l'ensemble en définissant le module en place:
module IntSet = Set (struct
type t = int
let lt a b = a < b
let eq a b = a = b
let leq a b = a <= b
end)