3

Why does the exponential operator use float variables in OCaml? Shouldn't it allow int variables too?

# 3**3;;
Error: This expression has type int but an expression was expected of type
         float

Works:

# 3.0**3.0;;
- : float = 27.
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
SadSeven
  • 1,247
  • 1
  • 13
  • 20
  • It couldn't allow `int` variables even if it wanted to, for the same reason that in the case of addition, an operation that is effectively defined for `int` and for `float`, the `float` version `+.` does not allow `int` arguments. This is a trade-off in order to enable type inference. Extensions to the Hindley-Milner typesystem are necessary (and some have been designed) to allow `5.0 + 5.0` and `5 + 5`. OCaml's shortest version is pretty acceptable in practice: with a recent version, you can use something like `Float.(5.0 + 5.0)`. – Pascal Cuoq Mar 31 '14 at 13:47
  • take a look at this similar question: http://stackoverflow.com/questions/16950687/integer-exponentiation-in-ocaml – Benoît Guédas Mar 31 '14 at 13:52

3 Answers3

3

So, the existing answers go into how to get around this, but not into why it is the case. There are two main reasons:

1) OCaml doesn't have operator aliasing. You can't have two operators that do the "same thing", but to different types. This means that only one kind of number, integers or floats (or some other representation) will get to use the standard ** interface.

2) pow(), the exponentiation function has historically been defined on floats (for instance, in Standard C).

Also, for another way to get around the problem, if you're using OCaml Batteries included, there is a pow function defined for integers.

slongfield
  • 101
  • 4
2

You can use int

let int_exp x y = (float_of_int x) ** (float_of_int y) |> int_of_float
Jackson Tale
  • 25,428
  • 34
  • 149
  • 271
  • I'm kinda new to Ocaml... Can you explain this part, please? |> int_of_float I don't know why is it there, or what it does. Thanks. – SadSeven Mar 31 '14 at 13:39
  • Oh ok, just got it... But why does it give error? # let int_exp x y = (float_of_int x) ** (float_of_int y) |> int_of_float;; let int_exp x y = (float_of_int x) ** (float_of_int y) |> int_of_float;; Error: Unbound value |> – SadSeven Mar 31 '14 at 13:41
  • 2
    @SadSeven the |> operator is included in libraries such as Core. It is also directly included in the language since v. 4.01. – Benoît Guédas Mar 31 '14 at 13:50
  • @Benoît Guédas I'm confused... do I have to include the library? Do I have an older version of the interpreter? How do I fix the error? – SadSeven Mar 31 '14 at 14:14
  • @SadServen to know your version, just type ocaml -version. You don't need this operator, you can simply write let int_exp x y = int_of_float ((float_of_int x) ** (float_of_int y)) – Benoît Guédas Mar 31 '14 at 14:19
  • @SadSeven Benoit's comments are all correct. http://www.realworldocaml.org is the place for you to really start to learn OCaml – Jackson Tale Mar 31 '14 at 19:45
0

There's a similar question: Integer exponentiation in OCaml

Here's one possible tail-recursive implementation of integer exponentiation:

let is_even n = 
  n mod 2 = 0

(* https://en.wikipedia.org/wiki/Exponentiation_by_squaring *)
let pow base exponent =
  if exponent < 0 then invalid_arg "exponent can not be negative" else
  let rec aux accumulator base = function
    | 0 -> accumulator
    | 1 -> base * accumulator
    | e when is_even e -> aux accumulator (base * base) (e / 2)
    | e -> aux (base * accumulator) (base * base) ((e - 1) / 2) in
  aux 1 base exponent
Community
  • 1
  • 1
Vladimir Keleshev
  • 13,753
  • 17
  • 64
  • 93