OCaml: types of restrictions in signatures

In my code, I have a database access context that provides elementary read / write operations called CouchDB.ctx. The various modules in my application then extend this class with additional features such as Async.ctx.

I am implementing a module Cachethat is wrapped around a module Source. The module functions Cachetake a context argument and manipulate the database. Then some calls are forwarded to the module Sourcealong with the context.

I need to define a functor along the lines of this:

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)

The problem is that I cannot express the fact that the context used by the module Sourcemust be a subtype CouchDB.ctx. The above code returns an error:

A type variable is unbound in this type declaration.
In type #CouchDB.ctx as 'a the variable 'a is unbound

?

+5
2

[...

:

module type SOURCE = sig
  type 'a ctx = 'a constraint 'a = #CouchDB.ctx
  type source
  val get : source -> 'a ctx -> string 
end

, , :

module type SOURCE = sig
  type source
  val get : source -> #CouchDB.ctx -> string 
end

: , OCaml . , , , . get CouchDB.ctx - , ( ), .

  val get : source -> CouchDB.ctx -> string 

, . CouchDB.ctx - , , . . : .

======]

2: , . , OCaml. . ,

module type SOURCE = sig
  type ctx < CouchDB.ctx
  ...
end

OCaml. , , :

module type SOURCE = sig
  type ctx
  val up : ctx -> CouchDB.ctx
  type source = string
  val get : source -> ctx -> string monad
end

Cache ctx#get (S.up ctx)#get, ctx#put.

module Cache = functor (S:SOURCE) -> struct
  type ctx = S.ctx
  type source = S.source
  let get source ctx = 
     bind ((S.up ctx)#get source) ...
end

module SomeSource = struct
  type ctx = AsyncDB.ctx
  let up ctx = (ctx : ctx :> CouchDB.ctx)
  type source = string
  let get s ctx = ...
end

module SomeCache = Cache (SomeSource)

, type source = string SOURCE. , ctx#get source Cache.

+5

, , :

module type SOURCE = sig
  class ctx : CouchDB.ctx
  type source
  val get : source -> ctx -> string
end

class ctx : CouchDB.ctx class-specification. OCaml

. , .

module type SOURCE = sig
  class type ctx = CouchDB.ctx
  type source
  val get : source -> ctx -> string
end

. , (, ).

+1

All Articles