Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify unary operators in OCaml?

In OCaml, it is very easy to access to a binary operator, such as "+":

# (+);;

( + ) : int -> int -> int

And modify them as I wish:

# let (+) = (+.);;

( + ) : float -> float -> float

In the Pervasives documentation, it says that (~-) is the unary operator corresponding to (-), meaning that ~-5 returns - :int = -5.

It is easy to modify (~-) as well:

let (~-) = (~-.);;

(~-) : float -> float

Fortunately, OCaml allows the user to use (-) as an alias for (~-):

Suppose we have defined

foo : int -> int -> int

We can call

foo 1 (-1);;

which is way better than

foo 1 (~-1);;

Well, the problem is, when I change (~-) definition, it doesn't affect the unary operator (-)...

let (~-) x = 5;;

~-2;;
- : int = 5

-2;;
- : int = -2

Any idea how to modify the unary (-) as well ?

like image 897
Romain360 Avatar asked Sep 18 '25 15:09

Romain360


2 Answers

As you said, unary (-) is a shortcut for (~-). Actually, your change has affected unary (-); for example, you have many ways to use (-) as you want after overriding (~-):

# - (2+0);;
- : int = 0

# let a = 2;;
val a : int = 2
# -a;;
- : int = 0

So it works when you pass an expression to (-). In case you call -2, it will be parsed as a value, not a function application. It makes sense to follow the normal convention of negative numbers.

BTW, I don't recommend you to use this way of overriding operators. Since you have change (-) for any datatype having that operator, it may lead to confusion and strange bugs.

like image 75
pad Avatar answered Sep 21 '25 15:09

pad


Here's a code extract from the compiler that seems to handle this case. Note that it only works for floating point constants. It's not a general feature of the - operator.

signed_constant:
    constant                                    { $1 }
  | MINUS INT                                   { Const_int(- $2) }
  | MINUS FLOAT                                 { Const_float("-" ^ $2) }
  | MINUS INT32                                 { Const_int32(Int32.neg $2) }
  | MINUS INT64                                 { Const_int64(Int64.neg $2) }

(You'll find this code in parser.mly.)

I don't think there's a way to get what you want without hacking on the compiler at this spot.

like image 39
Jeffrey Scofield Avatar answered Sep 21 '25 16:09

Jeffrey Scofield