Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7948499
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 4, 20262026-06-04T01:44:20+00:00 2026-06-04T01:44:20+00:00

In my code, I have a database access context that provides elementary read/write operations,

  • 0

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

I am implementing a Cache module which is wrapped around a Source module. The Cache module functions take a context argument and manipulate the database. Some calls are then forwarded to the Source module along 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 Source module should be a subtype of CouchDB.ctx. The above code returns the error:

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

How do I express this type constraint ?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-04T01:44:22+00:00Added an answer on June 4, 2026 at 1:44 am

    [Obsolete…

    The closest you can get is defining the signature as:

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

    But of course, you could as well just write:

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

    Edit: Note that OCaml uses structural typing for objects. That means that even if you wanted, you cannot get any more restrictive than the above. It does not even limit arguments to get to be instances of CouchDB.ctx or a derived class — any object that has (at least) the same methods will be compatible. Even when you write

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

    you can pass any object that has the same methods. The type CouchDB.ctx is just an abbreviation for a specific structural object type that happens to match the objects generated by the class of the same name. It is not restricted to those. And just to be sure: that is considered a feature.

    ======]

    Edit 2: With the extended example, I now see what you want and why. Unfortunately, that isn’t possible directly in OCaml. You would need partially abstract types. Namely, you would need to be able to write

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

    This is not available in OCaml. However, you can get close if you are willing to provide an explicit upcast in the signature:

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

    Then, in Cache, you have to replace occurrences of ctx#get with (S.up ctx)#get, and likewise for 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)
    

    Note that I also made type source = string transparent in the signature SOURCE. Without that, I cannot see how ctx#get source can possibly type-check in the Cache functor.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have used code like this: http://msdn.microsoft.com/en-us/library/dw70f090.aspx to access database before when working in
I have a database that uses codes. Each code can be anywhere from two
I have a code that creates a database with 2 tables in it. private
I have some code to update a database table that looks like try {
I have some code in my project that saves an object to the database,
I have an existing database based on SQLiteOpenHelper that has several versions and code
I have a web service that is quite heavy on database access. It works
I have a database that stores images which can be access via a primary
I have a class that uses linq to access the database. Some methods call
When performing many inserts into a database I would usually have code like this:

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.