私のコードには、と呼ばれる基本的な読み取り/書き込み操作を提供するデータベースアクセスコンテキスト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
このタイプの制約をどのように表現しますか?