Trong mã của tôi, tôi có một bối cảnh truy cập cơ sở dữ liệu cung cấp các hoạt động đọc/ghi sơ cấp, được gọi là CouchDB.ctx
. Các mô-đun khác nhau trong ứng dụng của tôi sau đó mở rộng lớp đó với chức năng bổ sung, chẳng hạn như Async.ctx
.OCaml: loại ràng buộc trong chữ ký
Tôi đang triển khai mô-đun Cache
được bao quanh mô-đun Source
. Các hàm Cache
mô-đun lấy một đối số ngữ cảnh và thao tác cơ sở dữ liệu. Một số cuộc gọi sau đó được chuyển tiếp đến mô-đun Source
cùng với ngữ cảnh.
tôi cần phải xác định một functor dọc theo dòng này:
module CouchDB = struct
class ctx = object
method get : string -> string option monad
method put : string -> string -> unit monad
end
end
module AsyncDB = struct
class ctx = object
inherit CouchDB.ctx
method delay : 'a. float -> (ctx -> 'a monad) -> 'a monad
end
end
module type SOURCE = sig
class ctx = #CouchDB.ctx (* <-- incorrect *)
type source
val get : source -> ctx -> string monad
end
module Cache = functor(S:SOURCE) -> struct
class ctx = S.ctx
type source = S.source
let get source ctx =
bind (ctx # get source) (function
| Some cache -> return cache
| None ->
bind (S.get source ctx)
(fun data -> bind (ctx # put source data)
(fun() -> return data))
end
module SomeSource = struct
class ctx = AsyncDB.ctx
type source = string
let get s ctx =
ctx # async 300 (some_long_computation s)
end
module SomeCache = Cache(SomeSource)
Vấn đề là tôi không thể diễn tả thực tế là bối cảnh được sử dụng bởi các module Source
phải là một subtype của CouchDB.ctx
. Mã trên trả về lỗi:
A type variable is unbound in this type declaration.
In type #CouchDB.ctx as 'a the variable 'a is unbound
Làm cách nào để thể hiện ràng buộc loại này?
Tôi tò mò về chữ ký 'SOURCE' của bạn. Khai báo trong tâm trí của tôi phải là 'loại mô-đun SOURCE = sig lớp ctx: đối tượng kế thừa kết thúc CouchDB.ctx (* ... *) end'; điều này không làm những gì bạn cần? –