Calling an infix function without using "open" or "include"

Suppose that an infix operator is defined inside a module. Then, I can call it from outside the module in the normal prefix way, i.e. by viewing it as a function. This is what the second line below does. Now, can I call this operator outside the module, while at the same time using infix notation and without opening or including the whole module ? The third line below tries to do this and fails.

utop # module Container=struct let (=||||=) a b =a+b end;;
module Container : sig val ( =||||= ) : int -> int -> int end
utop # Container.( =||||= ) 7 3;;
- : int = 10
utop # 7 (Container.( =||||= )) 3;;
Error: This expression has type int
       This is not a function; it cannot be applied.

You have to open the module (either globally or locally) if you want to use the operator in an infix way.
Note that you can use a local open to do something similar to your third line:

utop # Container.(7 =||||= 3);;
- : int = 10
4 Likes

From how you phrased your question, you might prefer to make a submodule (eg. Container.Ops or Container.Infix) which defines the infix operations. Then you can choose more precisely what to open or include.

module Container = struct
  module Ops = struct
    let (=||||=) a b = a + b
  end
  (* if you need access to Ops within this module, then 'open Ops' here *)
end

let fn_using_container_ops x y =
  let open Container.Ops in
  x =||||= y

I use this technique for most modules which define their own operators. If Ops should be opened along with the base module, include Ops in the module definition. For example, I have a V3 module for vectors of three-floats, which I will not open generally, but very commonly open V3.Ops, so all function calls have clear paths V3.normalize, while the distinct ops can be used freely: v +| w.

3 Likes