Get parametrized type definition from functor application

hi,

i’m stuck at getting a parametrized type from a functor.

module F (I:sig type t end) = struct
    type r = {id:int; v:I.t}
end

now i would like to get the type r in the output signature as a type parametrized by I.t. something like this wrong pseudocode:

type 'a rr = (F (struct type t end)).r with type t = 'a

i.e. i want the functor to build the type for me and then name it differently. is this possible?

maybe this is The Wrong Way? i considered making r parametrized by I.t but that doesn’t fly in my case. the reason is that i want to build a CCHeap on F; for this i add a compare function to F which only looks at the id field; that’s fine. but the input signature of CCHeap expects a non-parametized type F(I).t.

You should maybe try to describe what you are aiming for at a higher level? For example, would something like

type 'a rr = {id:int; v:'a}
module F(I:sig type t end) = struct
  type r = I.t rr
end

work for you?

hmm, maybe. i got the initial functor applications to work but after making the heap, it still fails. i simplified the actual situation a bit too much. here is what it’s “really” like with my current attempt:

type 'a rr = {id:int, v:'a}
module F (I:sig type t end) = struct
    type r = I.t rr
    let compare {id;_} {id';_} = Int.compare id id'
end
module H (I:sig type t end) = CCHeap.Make_from_compare (F (I))
type 'a rheap = (*what here? i want the type H.t for the heap above where I.t='a*)

i suspect i’m making it more convoluted than necessary? this may be due to the fact that i am trying to generalize a previous version of the program where the v field was monomorphic…

Since CCHeap creates an asbtract type, it doesn’t really make sense to define such a type constructor rheap since the type is dependent on the argument value given to CCHeap.Make_from_compare.

Typically, how were you planning to do anything with rheap ?

i guess i did not really think it through. later on, i have a function that takes a CCHeap.S.t as input. i would want this function to become polymorphic in the type of v. but iiuc, the fact that CCHeap.S.t is abstract makes this impossible. i still don’t understand if what i’m trying to do would be nonsense anyway (don’t see why) or if it’s just prevented by the way CCHeap is typed.

CCHeap.S.t is not a type since S is a signature. It sounds like what you really want is to implement a functor taking a module of type CCHeap.S as argument.

1 Like

yes, i guess that’s probably it. i agree that CCHeap.S.t is not a type. what i don’t really understand is why a ‘signature application’ F(sig type t end) (not actual OCaml) is not sufficient information to extract the type t of the output functor and then do something with it. so either i have not understood something basic about how functors work. or it could just be a question of the type t being made opaque by the output signature, preventing any spying into internals.

This cannot work with anonymous module. You are missing the fact that the type of a functor application is dependent on the value of its argument.

In particular, if you creates two maps from two different comparison function, you want
the resulting module to have incompatible types:

module Map1 = Map.Make(Int)
module Map2 = Map.Make(struct
  type t = int
  let compare x y = compare (x land 1, x lsr 1) (y land 1, y lsr 1)
end)

ah! i did not get that indeed. i thought that the ‘types’ level were independent of the ‘values’ level, which seemed intuitively plausible to me.
so the incompatibility between Map1 and Map2 is kind of a security feature i guess.