Subtype constraints in interfaces
Asked Answered
F

1

1

I want to compose several "traits" across several modules. A function might require multiple such "traits" as its input, i.e.:

type 'a x_t = < get_x : int ; .. > as 'a constraint 'a = < get_b : float ; .. >
val foo : x_t -> float 

composing these traits manually in the interface is cumbersome and error-prone, but perfectly possible.

But in an ideal world, I should be able to use the "trait's" name instead of manually composing all the required fields, i.e. write something like:

 type 'a x_t = < get_x : int ; .. > as 'a constraint 'a <: a_t

Unfortunately, the OCaml syntax does not allow for this. This seems to be a purely syntactical restriction, so I wonder whether there is a deeper reason for this?

In other words: Why can't I directly write subtype constraints in OCaml type signatures?

edit: To clarify the use-case: I have several (sometimes interdependent) modules which provide functionality on some common shared state. These modules shall be composable and loosely coupled (i.e., the only require their part of the global state to fulfill their needs and thus, I can always extend the state with new functionality). To achive this, the state is encapsulated in an object which provides several lenses (above I only used the getters, not the setters). Hence, if I provide interface definitions for my modules I need to describe the required lenses in the signature of my functions via constraints on the type parameter that encodes the whole state type. Now I am searching for a way to write these composed signature requirements as short and readable as possible.

Filings answered 30/6, 2014 at 9:29 Comment(3)
what is trait? You mean interface? In OCaml, all types of parameters or functions are inferred automatically. You just use, not defineMesothorium
for the explanation of "trait", see my edit above. Regarding type inference: I am aware of that feature but for modularity and readability I want to provide OCaml module signatures for all my modules.Filings
ah, ok. You are talking about functors in OCaml I guess. Basically, a functor itself is a module, which can be supplied to another module as parameter. And in this target module, it can invoke the functor's functions. It is better you give a concise example with your question, then I may be able to demonstrate functors using your example. Otherwise, here is a very good reading: realworldocaml.org/v1/en/html/functors.htmlMesothorium
U
8

If you define your traits as class types instead of object types, you can use the #foo syntax.

class type b = object
  method get_b : float
end

class type c = object
  method get_c : bool
end

type 'a x_t = < .. > as 'a 
  constraint 'a = #b
  constraint 'a = #c

You can also compose traits through the inheritance mechanism:

class type e = object
  inherit b inherit c
end

(Looks like types that are too clever for their own good, but why not experiment...)

Uthrop answered 30/6, 2014 at 12:4 Comment(3)
So basically "'a = #b" is a syntax for subtype constraints on classes? Is there any official documentation about that syntax? The specification seems not to mention the "#" type-operator.Filings
The notation is first mentioned in 3.11 polymorphic methods, within the definition of the class intlist.Pulmotor
If b is a class type, then #b is a polymorphic type whose instances are precisely the types of the objects that are instances of b. See the manual. constraint 'a = #b is just a special case of constraint 'a = <type expression>.Uthrop

© 2022 - 2024 — McMap. All rights reserved.