How does one work with different numeric types and modules like Int64

I should clarify that I’m using JaneStreet’s Base and I want to use bit operations on Int64 numbers

Int64 defines a lsl infix operator:

  val ( lsl ) : int64 -> int -> int64

and I want to describe some operation:

  ((1L lsl 2) - 1L) lsl (10 - 1)

this leads to bigger issues than anticipated:

  • lsl is moving an int64 number with int bits
    -> so I need to perform additions and subtractions and etc. on both int64 and int

initially I thought - I’ll just open Int64 since that’s what I need:

let do_things =
  let open Int64 in
  ((1L lsl 2) - 1L) lsl (10 - 1)

but - now works on int64, not int -> 10 - 1 doesn’t work
I tried defining an infix operator, so that I don’t need to open the whole Int64 module:

let ( lsl ) = Int64.shift_left
let do_things =
  ((1L lsl 2) - 1L) lsl (10 - 1)

but this doesn’t work either since - 1L now expects ints

the closest approximation to what I would fine useful has been:

let do_things =
  let shift = (10 - 1) in
  let open Int64 in
  ((1L lsl 2) - 1L) lsl shift

but it is fairly annoying to keep track of which syntax is overriden when;

How do people mix numeric operations of different types? is there a better way?
this is not very ergonomic

One way to handle this is to decide which operators you’re going to be using unqualified (only pick one module), and then do local opens for the rest. For example, if you pick Int64 to be primary:

let do_things =
  let open Int64.O in
  ((1L lsl 2) - 1L) lsl Int.(10 - 1)

(In Base, Int.O and similar modules expose just the operators, abs, neg, and zero in that module)

In more extreme cases, you might end up just using the operators as ordinary functions:

let do_things =
  Int64.shift_left (Int64.(-) (Int64.shift_left 1L 2) 1L) (10 - 1)

This is probably more appropriate if there’s just a couple of, say, int64 operations among a vast majority of int operations.

1 Like

Thanks @bcc32 I was not aware that you can open a module for a single operation, this is already much better;

I was hoping to get to something close to:

let do_things = ((1L <<< 2) - 1L) <<< (10 - 1)

but I guess in OCaml it’s not possible to have - infer int or int64 depending on the number?

Indeed, it is not. OCaml has no ad-hoc polymorphism (yet…)

1 Like

It’s a little ugly, but you could do something similar to what is done for the floating-point operators:

let (+%) = Base.Int64.(+)
let (-%) = Base.Int64.(-)
...

That would let you intermix the two operators because they would be distinguished by the extra character. Of course, you could choose something other than %: https://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char

thanks, got it, at least now it is more readable and looking forward to ad hoc polymorphism