En mi código, tengo un contexto de acceso a la base de datos que proporciona operaciones elementales de lectura/escritura, llamadas CouchDB.ctx
. Varios módulos en mi aplicación luego amplían esa clase con funcionalidad adicional, como Async.ctx
.OCaml: escriba constraints in signaturas
Estoy implementando un módulo Cache
que está envuelto alrededor de un módulo Source
. Las funciones del módulo Cache
toman un argumento de contexto y manipulan la base de datos. Algunas llamadas se envían al módulo Source
junto con el contexto.
I necesidad de definir un funtor a lo largo de las líneas de esto:
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)
El problema es que no puedo expresar el hecho de que el contexto utilizado por el módulo Source
debe ser un subtipo de CouchDB.ctx
. El código anterior devuelve el error:
A type variable is unbound in this type declaration.
In type #CouchDB.ctx as 'a the variable 'a is unbound
¿Cómo expreso esta restricción de tipo?
Tengo curiosidad sobre su firma 'SOURCE'. La declaración en mi mente debería ser 'module type SOURCE = sig class ctx: objeto hereda CouchDB.ctx end (* ... *) end'; ¿Esto no hace lo que necesitas? –