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 8823993
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 14, 20262026-06-14T06:29:49+00:00 2026-06-14T06:29:49+00:00

(A minimal non-compiling example can be found at https://gist.github.com/4044467 , see more background below.)

  • 0

(A minimal non-compiling example can be found at https://gist.github.com/4044467, see more background below.)

I am trying to implement Bootstrapped Heaps introduced in Chapter 10 of Okasaki’s Purely Functional Data Structure. The following is a simplified version of my non-compiling code.

We’re to implement a heap with following signature:

module type ORDERED =
sig
  type t
  val compare : t -> t -> int
end

module type HEAP =
sig
  module Elem : ORDERED

  type heap

  val empty : heap
  val insert : Elem.t -> heap -> heap
  val find_min : heap -> Elem.t
  val delete_min : heap -> heap
end

We say a data structure is bootstrapped when its implementation depends on another implementation of the same kind of data structure. So we have a heap like this (the actual implementation is not important):

module SomeHeap (Element : ORDERED) : (HEAP with module Elem = Element) =
struct
  module Elem = Element

  type heap

  let empty = failwith "skipped"
  let insert = failwith "skipped"
  let find_min = failwith "skipped"
  let delete_min = failwith "skipped"
end 

Then, the bootstrapped heap we’re going to implement, which can depend on any heap implementation, is supposed to have the following signature:

module BootstrappedHeap
  (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element)
  (Element : ORDERED) : (HEAP with module Elem = Element)

So we can use it like this:

module StringHeap = BootstrappedHeap(SomeHeap)(String)

The implementation of BootstrappedHeap, according to Okasaki, is like this:

module BootstrappedHeap
  (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element)
  (Element : ORDERED) : (HEAP with module Elem = Element) =
struct
  module Elem = Element

  module rec BootstrappedElem :
  sig
    type t =
      | E
      | H of Elem.t * PrimH.heap
    val compare : t -> t -> int
  end =
  struct
    type t =
      | E
      | H of Elem.t * PrimH.heap
    let compare t1 t2 = match t1, t2 with
      | H (x, _), H (y, _) -> Elem.compare x y
      | _ -> failwith "unreachable"
  end
  and PrimH : (HEAP with module Elem = BootstrappedElem) =
    MakeH(BootstrappedElem)

  type heap

  let empty = failwith "not implemented"
  let insert = failwith "not implemented"
  let find_min = failwith "not implemented"
  let delete_min = failwith "not implemented"
end

But this is not compiling! The error message is:

File "ordered.ml", line 52, characters 15-55:
Error: In this `with' constraint, the new definition of Elem
       does not match its original definition in the constrained signature:
       Modules do not match:
         sig type t = BootstrappedElem.t end
       is not included in
         ORDERED
       The field `compare' is required but not provided

The line 52 is the line

and PrimH : (HEAP with module Elem = BootstrappedElem) =

I think BootstrappedElem did implement ORDERED as it has both t and compare, but I failed to see why the compiler fails to find the compare function.

Change the signature of BootstrappedElem to

module rec BootstrappedElem : ORDERED

will make it compiling but this will hide the type constructor E and T in BootstrappedElem to make it impossible to implement the later parts.

The whole non-compiling code can be downloaded at https://raw.github.com/gist/4044281/0ce0336c40b277e59cece43dbadb9b94ce6efdaf/ordered.ml

  • 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-14T06:29:51+00:00Added an answer on June 14, 2026 at 6:29 am

    I believe this might be a bug in the type-checker. I have reduced your code to the following example:

    module type ORDERED =
    sig
      type t
      val compare : t -> t -> int
    end
    
    
    module type CARRY = sig
      module M : ORDERED
    end
    
    (* works *)
    module HigherOrderFunctor
      (Make : functor (X : ORDERED) -> (CARRY with module M = X))
    = struct
      module rec Base
        : (ORDERED with type t = string)
        = String
      and Other
        : (CARRY with module M = Base)
        = Make(Base)
    end
    
    (* does not work *)
    module HigherOrderFunctor
      (Make : functor (X : ORDERED) -> (CARRY with module M = X))
    = struct
      module rec Base
        : sig
          (* 'compare' seems dropped from this signature *)
          type t = string
          val compare : t -> t -> int
        end
        = String
      and Other
        : (CARRY with module M = (Base : sig type t = string val compare : t -> t -> int end))
        = Make(Base)
    end
    

    I don’t understand why the first code works and the second (which seems equivalent) doesn’t. I suggest you wait a bit to see if an expert comes with an explanation (Andreas?), then consider sending a bug report.

    In this case, a solution is to first bind the signature that seems mishandled:

    (* works again *)
    module HigherOrderFunctor
      (Make : functor (X : ORDERED) -> (CARRY with module M = X))
    = struct
      (* bind the problematic signature first *)
      module type S = sig
        type t = string
        val compare : t -> t -> int
      end
    
      module rec Base : S = String
      and Other : (CARRY with module M = Base) = Make(Base)
    end
    

    However, that is not possible in your setting, because the signature of BootstrappedElem is mutually recursive with BootstrappedHeap.

    A workaround is to avoid the apparently-delicate with module ... construct and replace it with a simple type equality with type Elem.t = ...:

    module BootstrappedHeap
      (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element)
      (Element : ORDERED) : (HEAP with module Elem = Element) =
    struct
      module Elem = Element
    
      module rec BootstrappedElem :
      sig
        type t =
          | E
          | H of Elem.t * PrimH.heap
        val compare : t -> t -> int
      end =
      struct
        type t =
          | E
          | H of Elem.t * PrimH.heap
        let compare t1 t2 = match t1, t2 with
          | H (x, _), H (y, _) -> Elem.compare x y
          | _ -> failwith "unreachable"
      end
      and PrimH : (HEAP with type Elem.t = BootstrappedElem.t) =
        MakeH(BootstrappedElem)
    
      type heap
    
      let empty = failwith "not implemented"
      let insert = failwith "not implemented"
      let find_min = failwith "not implemented"
      let delete_min = failwith "not implemented"
    end
    

    You could also avoid the mutual recursion and define both BootstrappedElem and BootstrappedHeap in one recursive knot, by defining BootstrappedElem inside the recursive BootstrappedHeap.

    module BootstrappedHeap
      (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element)
      (Element : ORDERED) : (HEAP with module Elem = Element) =
    struct
      module rec BootstrappedHeap : sig
        module Elem : sig
          type t = E | H of Element.t * BootstrappedHeap.heap
          val compare : t -> t -> int
        end        
        include (HEAP with module Elem := Elem)
      end = struct
        module Elem = struct
          type t = E | H of Element.t * BootstrappedHeap.heap
          let compare t1 t2 = match t1, t2 with
            | H (x, _), H (y, _) -> Element.compare x y
            | _ -> failwith "unreachable"
        end
        include (MakeH(Elem) : HEAP with module Elem := Elem)
      end
    
      module Elem = Element
    
      type heap
    
      let empty = failwith "not implemented"
      let insert = failwith "not implemented"
      let find_min = failwith "not implemented"
      let delete_min = failwith "not implemented"
    end
    

    This style corresponds naturally to your decision of embedding Elem in the HEAP signature and using with module ... for refinement. Another solution would have been to define HEAP as a functor returning a signature, used as HEAP(Elem).S, and I suppose a different recursive style could have been chosed. Not to say that this would have been better: I think the “abstract module” style is more convenient.

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

Sidebar

Related Questions

Somehow, I can't seem to correctly implement a SortedMap. Here's a minimal (non-)working example:
Anyone have an minimal example of ASP.NET MVC and dotnetcharting.com control lying around? Thanks,
In C, function declarations can be prototype or non-prototype declarations. For example, consider the
A minimal illustrative Xcode project for this is available on github . On my
Edit: a minimal project that exhibits the crash can be downloaded from crashTest .
Take the following minimal example: import abc class FooClass(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def
I am experimenting by statically compiling a minimal program and examining the system calls
Minimal code: // --------inline.h-------- struct X { static inline void foo (); }; #ifdef
A minimal code that reproduces the problem is as follows: <div class=cell> <input type=text
The following minimal test case throws an error in powershell: [reflection.assembly]::LoadWithPartialName('system.xml.linq') [system.xml.linq.xdocument]::parse('<node>&</node>') and frankly,

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.