How can (-) seemingly have two different types?
This was a design decision in the language. -1
is a number, but its usage in this context is not related to the function (-)
. (As Ackdari mentions in their answer, this usage is related to the function negate
.) There are a couple compromises that allow this to work:
You cannot take a right slice of the
(-)
operator. As a workaround, Haskell provides thesubtract
function.You cannot write a negative integer without parentheses unless it is at the beginning of an assignment (e.g. directly after
=
or->
). This produces a parse error:let x = 8 * -1
Instead, it should be written as
let x = 8 * (-1)
However, this is fine:
let x = -1 * 8
These were considered to be reasonable tradeoffs to the designers of the language.
Unary minus is special in Haskell. As stated in section 3.4 of the Report:
The special form
-e
denotes prefix negation, the only prefix operator in Haskell, and is syntax fornegate (e)
. The binary-
operator does not necessarily refer to the definition of-
in the Prelude; it may be rebound by the module system. However, unary-
will always refer to thenegate
function defined in the Prelude. There is no link between the local meaning of the-
operator and unary negation.
The answer is already descirbed in the haskell-wiki, it states
The unary minus is syntactic sugar for the Prelude function
negate
so the function (-)
is always the a - b
function and if you write code like
let x = -y
the compiler will translate it to let x = negate y
.