Different type inference with Base?

Hi. I’m new to OCaml and bumped up against a difference in Base that I wasn’t sure how to troubleshoot so I’m reaching out here. This function works in utop when I haven’t opened Base.

#require "owl";;
open Owl;;
let get_num_events max_obs max_time =
  let rec loop obs time events =
    if (obs > max_obs || time > max_time) then (events - 1)
    else let exp_draw = Stats.exponential_rvs ~lambda:(Float.of_int obs) in
    loop (obs + 1) (time +. exp_draw) (events + 1) in
  loop 1 0. 0
;;

However, if I open Base and re-run get_num_events, I get this error:

Line 5, characters 20-24:
Error: This expression has type int but an expression was expected of type
         float

How can I change get_num_events so that it will compile with Base?

In Base, the default comparison operators are those for int, rather than the polymorphic ones: GitHub - janestreet/base: Standard library for OCaml. This blog post explains some of the motivations for this.

Therefore, in the expression time > max_time, both time and max_time are inferred to be ints, whereas without Base, they are inferred to both be the same, unknown type 'a which is only inferred to be float once the compiler gets to time +. exp_draw. You can use Float.(>) to explicitly select the float comparison operator and fix the type error.

2 Likes

I think that Base replaces the polymorphic > with the int one. You can either locally open Stdlib in the definition (I think it is called Caml in base) or specify that you are comparing floats:

let get_num_events max_obs max_time =
  let (>.) = Base.Float.(>) in
  let rec loop obs time events =
    if (obs > max_obs || time >. max_time) then (events - 1)
    else let exp_draw = Stats.exponential_rvs ~lambda:(Float.of_int obs) in
    loop (obs + 1) (time +. exp_draw) (events + 1) in
  loop 1 0. 0
;;
1 Like