What are the differences between the unary minus and unary tilde minus operators in ocaml? - operators

I'm learning OCaml, and the docs and books I'm reading aren't very clear on some things.
In simple words, what are the differences between
-10
and
~-10
To me they seem the same. I've encountered other resources trying to explain the differences, but they seem to explain in terms that I'm not yet familiar with, as the only thing I know so far are variables.

In fact, - is a binary operator, so some expression can be ambigous : f 10 -20 is treated as (f 10) - 20. For example, let's imagine this dummy function:
let f x y = (x, y)
If I want produce the tuple (10, -20) I naïvely would write something like that f 10 -20 which leads me to the following error:
# f 10 -20;;
Error: This expression has type 'a -> int * 'a
but an expression was expected of type int
because the expression is evaluated as (f 10) - 20 (so a substract over a function!!) so you can write the expression like this: f 10 (-20), which is valid or f 10 ~-20 since ~- (and ~+ and ~-. ~+. for floats) are unary operators, the predecense is properly respected.

It is easier to start by looking at how user-defined unary (~-) operators work.
type quaternion = { r:float; i:float; j:float; k:float }
let zero = { r = 0.; i = 0.; j = 0.; k = 0. }
let i = { zero with i = 1. }
let (~-) q = { r = -.q.r; i = -.q.i; j = -. q.j; k = -. q.k }
In this situation, the unary operator - (and +) is a shorthand for ~- (and ~+) when the parsing is unambiguous. For example, defining -i with
let mi = -i
works because this - could not be the binary operator -.
Nevertheless, the binary operator has a higher priority than the unary - thus
let wrong = Fun.id -i
is read as
let wrong = (Fun.id) - (i)
In this context, I can either use the full form ~-
let ok' = Fun.id ~-i
or add some parenthesis
let ok'' = Fun.id (-i)
Going back to type with literals (e.g integers, or floats), for those types, the unary + and - symbol can be part of the literal itself (e.g -10) and not an operator. For instance redefining ~- and ~+ does not change the meaning of the integer literals in
let (~+) = ()
let (~-) = ()
let really = -10
let positively_real = +10
This can be "used" to create some quite obfuscated expression:
let (~+) r = { zero with r }
let (+) x y = { r = x.r +. y.r; i = x.i +. y.i; k = x.k +. x.k; j =x.k +. y.j }
let ( *. ) s q = { r = s *. q.r; i = s *. q.i; j = s *. q.j; k = s *. q.k }
let this_is_valid x = +x + +10. *. i

OCaml has two kinds of operators - prefix and infix. The prefix operators precede expressions and infix occur in between the two expressions, e.g., in !foo we have the prefix operator ! coming before the expression foo and in 2 + 3 we have the infix operator + between expressions 2 and 3.
Operators are like normal functions except that they have a different syntax for application (aka calling), whilst functions are applied to an arbitrary number of arguments using a simple syntax of juxtaposition, e.g., f x1 x2 x3 x41, operators can have only one (prefix) or two (infix) arguments. Prefix operators are very close to normal functions, cf., f x and !x, but they have higher precedence (bind tighter) than normal function application. Contrary, the infix operators, since they are put between two expressions, enable a more natural syntax, e.g., x + y vs. (+) x y, but have lower precedence (bind less tight) than normal function application. Moreover, they enable chaining several operators in a row, e.g., x + y + z is interpreted as (x + y) + z, which is much more readable than add (add (x y) z).
Operators in OCaml distinguished purely syntactically. It means that the kind of an operator is fully defined by the first character of that operator, not by a special compiler directive, like in some other languages (i.e., there is not infix + directive in OCaml). If an operator starts with the prefix-symbol sequence, e.g., !, ?#, ~%, it is considered as prefix and if it starts with an infix-symbol then it is, correspondingly, an infix operator.
The - and -. operators are treated specially and can appear both as prefix and infix. E.g., in 1 - -2 we have - occurring both in the infix and prefix positions. However, it is only possible to disambiguate between the infix and the prefix versions of the - (and -.) operators when they occur together with other operators (infix or prefix), but when we have a general expression, the - operator is treated as infix. E.g., max 0 -1 is interpreted as (max 0) - 1 (remember that operator has lower precedence than function application, therefore when they two appear with no parentheses then functions are applied first and operators after that). Another example, Some -1, which is interpreted as Some - 1, not as Some (-1). To disambiguate such code, you can use either the parentheses, e.g., max 0 (-1), or the prefix-only versions, e.g, Some ~-1 or max 0 ~-1.
As a matter of personal style, I actually prefer parentheses as it is usually hard to keep these rules in mind when you read the code.
1) Purists will say that functions in OCaml can have only one argument and f x1 x2 x3 x4 is just ((f x1) x2) x3) x4, which would be a totally correct statement, but a little bit irrelevant to the current discussion.

Related

When should you use plus, minus, times functions instead of using the operators in Kotlin?

I cannot think of a case where using the Kotlin built-in plus, minus, times etc. functions would return a different result from just using the corresponding operators (+, -, *). Why would you ever want to use these functions in your Kotlin code?
Just in case you aren't aware, these are operator overloads. The named functions are how the operators' functionality is defined.
There is a case for using the named versions. The function calls don't pay attention to operator precedence and are evaluated sequentially if you chain them.
val x = 1
val y = 2
val z = 3
println(x + y * z) // equivalent to 1 + (2 * 3) -> 7
println(x.plus(y).times(z)) // equivalent to (1 + 2) * 3 -> 9
This could be clearer than using the operators if you have a lot of nested parentheses, depending on the context of the type of math you're doing.
result = ((x - 7) * y - z) * 10
// vs
result = x.minus(7).times(y).minus(z).times(10)
It's not really applicable for basic algebra like this, but you might have classes with operator overloads where the logic can be more easily reasoned through with the sequential approach.
By explicitly stating function names you can perform a safe call on a nullable number which cannot be done with an operator.
For example:
fun doubleOrZero(num: Int?) : Int {
return num?.times(2) ?: 0
}

How does the Prelude allow numeric literals for Nat?

In Type-Driven Development with Idris ch. 4, they say
The Prelude also defines functions and notation to allow Nat to be used like any other numeric type, so rather than writing S (S (S (S Z))), you can simply write 4.
and similarly for Fin. How does it achieve that? I've looked at the source but I can't figure it out.
from where you linked notice fromIntegerNat:
||| Convert an Integer to a Nat, mapping negative numbers to 0
fromIntegerNat : Integer -> Nat
fromIntegerNat 0 = Z
fromIntegerNat n =
if (n > 0) then
S (fromIntegerNat (assert_smaller n (n - 1)))
else
Z
and fromInteger in the Num implementation of Nat:
Num Nat where
(+) = plus
(*) = mult
fromInteger = fromIntegerNat
and Cast Integer Nat
||| Casts negative `Integers` to 0.
Cast Integer Nat where
cast = fromInteger
In the case of Idris1 it will attempt to cast from a literal (such as Char, String or Integer) into whatever type is required via those "fromFunctions" (as noted in a comment in one of the above sources: [...] '-5' desugars to 'negate (fromInteger 5)') and in general Idris1 supports implicit casting for any two types. ( http://docs.idris-lang.org/en/latest/tutorial/miscellany.html#implicit-conversions )
In the case of Idris2, there are some pragmas (%charLit fromChar, %stringLit fromString, %integerLit fromInteger) to hint the compiler to use some cast function from a literal into any other type.

OCaml Syntax Error fixed by double semicolon

I'm sorry for asking such a basic question here, but I'm getting a syntax error when trying to compile the following code,
let sum_of_squares_of_two_largest x y z =
let a :: b :: _ = List.sort (fun x y -> -(compare x y)) [x; y; z] in
a * a + b * b;
let rec factorial n =
if n = 0 then 1 else n * factorial (n - 1);
let e_term n = 1.0 /. float_of_int (factorial n);
let rec e_approximation n =
if n = 0 then (e_term 0) else (e_term n) +. (e_approximation (n - 1));
let rec is_even x = if x = 0 then true else is_odd (x - 1);
and is_odd x = not (is_even x);
let rec f_rec n =
if n < 3 then n else f_rec(n - 1) + 2 * f_rec(n - 2) + 3 * f_rec(n - 3);
The uninformative compiler tells me there is syntax error on line 19, which is the last line of the file.
File "source.ml", line 19, characters 0-0:
Error: Syntax error
That is, line 19 is a blank line, only with a new-line character.
I can "fix" this syntax error by adding ;; at the end of each function definition instead of the ;.
Am I missing a semicolon somewhere?
As has been pointed out in the comments, ; is not a statement terminator like in many other (Algol-inspired) languages, but a sequence operator. It takes two values, throws away the first (but warns if it is not unit) and returns the second. a; b is therefore roughly equivalent to let _ = a in b.
You say you would have expected the error to say something like ';' is missing the second operand., but the thing is: it doesn't. Not until it reaches the end of the file (at which point the error message certainly could have been more intelligent, but probably not very accurate anyway).
What follows each ; in your code looks like a perfectly valid expression that might yield a value. For example, if let rec factorial n = ...; had been let rec factorial n = ... in 2 The value of the expression would have been 2. The problem here, from the compiler's point of view, is that it runs out of file before the expression is finished.
As you've also found out, ;; actually is a statement terminator. Or perhaps a toplevel definition terminator is a better term (I don't know if it even has an official name). It's used in the REPL to terminate input, but isn't needed in normal OCaml code unless you mix toplevel definitions and expressions, which you never should.
;; can still be useful for beginners as a "bulkhead", however. If you put just one ;; in place of a ; in the middle of your file, you'll find the compiler now points the error location there. That's because ;; terminates the definition without the preceding expression being complete. So you now know there's an error before that. (Actually in the preceding expression, but since your entire file is one single expression, "before that" is really the best we can do).

Unique variable names in Z3

I need to rely on the fact that two Z3 variables
can not have the same name.
To be sure of that,
I've used tuple_example1() from test_capi.c in z3/examples/c and changed the original code from:
// some code before that ...
x = mk_real_var(ctx, "x");
y = mk_real_var(ctx, "y"); // originally y is called "y"
// some code after that ...
to:
// some code before that ...
x = mk_real_var(ctx, "x");
y = mk_real_var(ctx, "x"); // but now both x and y are called "x"
// some code after that ...
And (as expected) the output changed from:
tuple_example1
tuple_sort: (real, real)
prove: get_x(mk_pair(x, y)) = 1 implies x = 1
valid
disprove: get_x(mk_pair(x, y)) = 1 implies y = 1
invalid
counterexample:
y -> 0.0
x -> 1.0
to:
tuple_example1
tuple_sort: (real, real)
prove: get_x(mk_pair(x, y)) = 1 implies x = 1
valid
disprove: get_x(mk_pair(x, y)) = 1 implies y = 1
valid
BUG: unexpected result.
However, when I looked closer, I found out that Z3 did not really fail or anything, it is just a naive (driver) print out to console.
So I went ahead and wrote the exact same test with y being an int sort called "x".
To my surprise, Z3 could handle two variables with the same name when they have different sorts:
tuple_example1
tuple_sort: (real, real)
prove: get_x(mk_pair(x, y)) = 1 implies x = 1
valid
disprove: get_x(mk_pair(x, y)) = 1 implies y = 1
invalid
counterexample:
x -> 1.0
x -> 0
Is that really what's going on? or is it just a coincidence??
Any help is very much appreciated, thanks!
In general, SMT-Lib does allow repeated variable names, so long as they have different sorts. See page 27 of the standard. In particular, it says:
Concretely, a variable can be any symbol, while a function symbol
can be any identifier (i.e., a symbol or an indexed symbol). As a
consequence, contextual information is needed during parsing to know
whether an identifier is to be treated as a variable or a function
symbol. For variables, this information is provided by the three
binders which are the only mechanism to introduce variables. Function
symbols, in contrast, are predefined, as explained later. Recall that
every function symbol f is separately associated with one or more
ranks, each specifying the sorts of f’s arguments and result. To
simplify sort checking, a function symbol in a term can be annotated
with one of its result sorts σ. Such an annotated function symbol is a
qualified identifier of the form (as f σ).
Also on page 31 of the same document, it further clarifies "ambiguity" thusly:
Except for patterns in match expressions, every occurrence of an
ambiguous function symbol f in a term must occur as a qualified
identifier of the form (as f σ) where σ is the intended output sort of
that occurrence
So, in SMT-Lib lingo, you'd write like this:
(declare-fun x () Int)
(declare-fun x () Real)
(assert (= (as x Real) 2.5))
(assert (= (as x Int) 2))
(check-sat)
(get-model)
This produces:
sat
(model
(define-fun x () Int
2)
(define-fun x () Real
(/ 5.0 2.0))
)
What you are observing in the C-interface is essentially a rendering of the same. Of course, how much "checking" is enforced by the interface is totally solver specific as SMT-Lib says nothing about C API's or API's for other languages. That actually explains the BUG line you see in the output there. At this point, the behavior is entirely solver specific.
But long story short, SMT-Lib does indeed allow two variables have the same name used so long as they have different sorts.

When (exactly) can equality be proposed between different types using '='?

In the documentation, it says:
Equality in Idris is heterogeneous, meaning that we can even propose
equalities between values in different types:
idris_not_php : 2 = "2"
That particular example compiles, but the hole is presented as being of type fromInteger 2 = "2". Given that fromInteger 2 can belong to any type that is an instance of Num, maybe the compiler isn't quite clever enough to deduce that the value of 2 is not a String?
In comparison, the following slightly different code fails to compile:
idris_not_php : S (S Z) = "2"
The compiler reports a type mismatch between Nat and String.
Also, the following does compile successfully:
Num String where
(+) x y = y
(*) x y = y
fromInteger n = "2"
idris_not_php : 2 = "2"
idris_not_php = the (the String 2 = "2") Refl
And these two compile:
idris_not_php : S (S Z) ~=~ "2"
idris_not_php = ?hole
two_is_two : 2 ~=~ 2
two_is_two = Refl
Is there any particular rule about when = can be used between things that are of different types, or is it just a matter of using ~=~ when = doesn't work? Are ~=~ and = semantically identical, and if so, why is ~=~ even necessary?
This answer have some theoretical notes about heterogeneous equality in Idris. And this answer has example of why you may need (~=~).
I just want to add a little about idris_not_php : 2 = "2" example. This can be type checked if you have Num instance for String type just as you did. Integral constants in Idris are polymorphic. Though, any reasonable program wouldn't have such instance for String because it doesn't make sense.