What is the meaning of this signature for `String.sub`: `(string, string) Blit.sub`

Viewed 58

I am learning / playing with ocaml in utop. Following the real world ocaml book.

So naturally I started with:

open Base;;

Next I try:

utop # String.sub "Hello world!" 3 4;;
Line 1, characters 0-10:
Warning 6 [labels-omitted]: labels pos, len were omitted in the application of this function.
Line 1, characters 0-10:
Warning 6 [labels-omitted]: labels pos, len were omitted in the application of this function.
- : string = "lo w"

Okay, more or less as expected. Base replaces many standard functions like String.sub with versions that use labeled arguments for clarity (arguably a good thing, so I have no complaint about that really).

But here's what's confusing to me. When I try to check the signature / type of the improved String.sub, I expected to see an improved function signature similar to the 'standard' String.sub signature (string -> int -> int -> string) but with labeled arguments. What I see instead is this:

utop # String.sub;;
- : (string, string) Blit.sub = <fun>

What is the meaning of that? And how can a (naive) user use this to determine the proper way to call the String.sub function?

I.e. how do I find out from a signature like (string, string) Blit.sub...

  • that it is a function?
  • what types of arguments it expects?
  • what labels it expects on the arguments?
  • what type of value it returns?
1 Answers

Blit.sub is a type alias for a function type. But let's discover it ourselves. We can use the #show directive on the output to inspect its type, up until we get a satisfactory result,

# #show String.sub;;
val sub : (Base.String.t, Base.String.t) Base__.Blit.sub
# #show Base__.Blit.sub;;
type ('src, 'dst) sub = ('src, 'dst) Base__.Blit_intf.sub
# #show Base__.Blit_intf.sub;;
type ('src, 'dst) sub = 'src -> pos:int -> len:int -> 'dst

Now let's substitute the 'src and 'dst parameters with string, since we have (string, string) sub, and we get, the type of the String.sub

String.sub : string -> pos:int -> len:int -> string

It is much easier if you're using merlin and a suitable code editor. You can just ask the editor to unfold the type, so it takes several milliseconds to get to the root, and Merlin will also perform the substitution for you. For example, in my Emacs, it is just several repetitions of C-c C-t on the type. The same is for documentation that could easily be brought in by a single keystroke (not in this case though, as this function lacks documentation in Base). You can also easily jump to the definition or declaration of the function. So, if you want to be effective in OCaml, consider setting up a good development environment, like Emacs, Vim, Visual Studio Code, or some other.

Related