Natknąłem się na dość prosty problem z OCaml, ale nie mogę znaleźć eleganckiego rozwiązania. Pracuję z funktorami, które są stosowane do względnie prostych modułów (zazwyczaj definiują typ i kilka funkcji tego typu) i rozszerzają te proste moduły o dodatkowe, bardziej złożone funkcje, typy i moduły. Uproszczona wersja będzie:Moduły i pola rekordów
module type SIMPLE = sig
type t
val to_string : t -> string
val of_string : string -> t
end
module Complex = functor (S:SIMPLE) -> struct
include S
let write db id t = db # write id (S.to_string t)
let read db id = db # read id |> BatOption.map S.of_string
end
Nie ma potrzeby, aby dać prosty moduł nazwę, ponieważ wszystkie jego funkcjonalność jest obecna w rozszerzonym modułem, a funkcje w prosty moduł są generowane przez camlp4 w zależności od typu . Idiomatyczne wykorzystanie tych funktorów jest:
module Int = Complex(struct
type t = int
end)
Problem pojawia się, gdy pracuję z zapisów:
module Point2D = Complex(struct
type t = { x : int ; y : int }
end)
let (Some location) = Point2D.read db "location"
Wydaje się, że nie prosty sposób dostępu pola x
i y
określono powyżej od poza modułem Point2D
, takim jak location.x
lub location.Point2D.x
. Jak mogę to osiągnąć?
EDIT: zgodnie z wnioskiem, oto pełna minimalny przykład, który pokazuje problem:
module type TYPE = sig
type t
val default : t
end
module Make = functor(Arg : TYPE) -> struct
include Arg
let get = function None -> default | Some x -> (x : t)
end
module Made = Make(struct
type t = {a : int}
let default = { a = 0 } (* <-- Generated by camlp4 based on type t above *)
end)
let _ = (Made.get None).a (* <-- ERROR *)
Zamieszczanie kodu umożliwiającego kompilację bardzo pomogłoby uzyskać kompilowalne odpowiedzi. –