В моем коде у меня есть контекст доступа к базе данных, который обеспечивает элементарные операции чтения/записи, называемые CouchDB.ctx.
. Затем различные модули в моем приложении расширяют этот класс дополнительными функциями, такими как Async.ctx
.
Я реализую модуль 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
Как мне выразить это ограничение типа?