В моем коде у меня есть контекст доступа к базе данных, который обеспечивает элементарные операции чтения/записи, называемые CouchDB.ctx
. Различные модули в моем приложении затем расширяют этот класс с дополнительными функциями, такими как Async.ctx
.OCaml: ограничения типа в подписях
Я реализую модуль Cache
, который обернут вокруг модуля Source
. Функции модуля Cache
принимают аргумент контекста и манипулируют базой данных. Затем некоторые вызовы пересылаются в модуль Source
вместе с контекстом.
мне нужно определить функтор вдоль линий этого:
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)
Проблема заключается в том, что я не могу выразить тот факт, что контекст, используемый Source
модуль должен быть подтипом CouchDB.ctx
. Приведенный выше код возвращает ошибку:
A type variable is unbound in this type declaration.
In type #CouchDB.ctx as 'a the variable 'a is unbound
Как выразить это ограничение типа?
Мне любопытно ваша подпись 'SOURCE'. Декларация в моем сознании должна быть 'module type SOURCE = sig class ctx: object inherit CouchDB.ctx end (* ... *) end'; делает ли это не то, что вам нужно? –