Skip to content

Commit 6a15a2f

Browse files
authored
Merge pull request documentationjs#21 from purescript/rearrange-values-syntax
Move Values.md into Syntax.md, fixes documentationjs#17
2 parents d94b9b2 + 3f93ba7 commit 6a15a2f

File tree

4 files changed

+446
-414
lines changed

4 files changed

+446
-414
lines changed

guides/Common-Operators.md

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Common Operators
2+
3+
Or, "what is the PureScript equivalent of \<X operator\> in JS?"
4+
5+
Although the PureScript language defines no built-in operators, plenty are defined in the `Prelude` and other core libraries. This guide gives you a overview of these operators and the corresponding operators in JavaScript.
6+
7+
## JavaScript's unary operators
8+
9+
All PureScript operators are binary, with one exception: there is syntax sugar for unary negation, whereby in PureScript code, `-x` is desugared to `negate x`, which uses whichever `negate` is in scope.
10+
11+
This means that the PureScript analogues to unary JavaScript operators (other than `-`) are not operators, but normal functions which must be applied using the standard prefix-style function application, so e.g. `!x` in JS must be written as `not x` in PureScript.
12+
13+
| JS Operator | PureScript Function | Defined in | Meaning |
14+
|-------------|---------------------|-----------------------|------------------|
15+
| `-` | `negate` | `Data.Ring` | Numeric negation |
16+
| `!` | `not` | `Data.HeytingAlgebra` | Boolean negation |
17+
| `~` | `complement` | `Data.Int.Bits` | Bitwise negation |
18+
19+
## JavaScript's binary operators
20+
21+
| JS Operator | PureScript Function | Defined in | Meaning |
22+
|-------------|---------------------|-----------------------|------------------------------------------|
23+
| `+` | `+` | `Data.Semiring` | Numeric addition |
24+
| `+` | `<>` | `Data.Semigroup` | String concatenation |
25+
| `-` | `-` | `Data.Ring` | Numeric subtraction |
26+
| `*` | `*` | `Data.Semiring` | Numeric multiplication |
27+
| `/` | `/` | `Data.EuclideanRing` | Numeric division |
28+
| `%` | `%` (see note) | `Math` | Remainder, the same as JS' `%` operator. |
29+
| `%` | `mod` (see note) | `Data.EuclideanRing` | Also remainder (see note) |
30+
| `==` | `==` | `Data.Eq` | Equality check |
31+
| `!=` | `/=` | `Data.Eq` | Inequality check |
32+
| `<` | `<` | `Data.Ord` | Less than |
33+
| `<=` | `<=` | `Data.Ord` | Less than or equal |
34+
| `>` | `>` | `Data.Ord` | Greater than |
35+
| `>=` | `>=` | `Data.Ord` | Greater than or equal |
36+
| `&&` | `&&` | `Data.HeytingAlgebra` | Boolean AND |
37+
| `||` | `||` | `Data.HeytingAlgebra` | Boolean OR |
38+
| `&` | `.&.` | `Data.Int.Bits` | Bitwise AND |
39+
| `|` | `.|.` | `Data.Int.Bits` | Bitwise OR |
40+
| `^` | `.^.` | `Data.Int.Bits` | Bitwise XOR |
41+
| `<<` | `shl` | `Data.Int.Bits` | Shift Left |
42+
| `>>` | `shr` | `Data.Int.Bits` | Shift Right |
43+
| `>>>` | `zshr` | `Data.Int.Bits` | Zero-fill Shift Right |
44+
45+
Most of these functions and operators are re-exported by the `Prelude`, so to have access to them in your code, you should normally just write `import Prelude`.
46+
47+
Additionally, many of these functions and operators are defined in type classes and work with lots of different types. For example, `+` and `*` work with not only `Int` and `Number`, but also any instance of the `Semiring` type class defined in the `Prelude`.
48+
49+
### A note on remainder/modulus (`%`)
50+
51+
Normally, when we ask for the remainder of one number after dividing by another, we are talking about integers. Clearly the remainder of 10 after dividing by 3 is 1, and indeed in JS, `10 % 3 == 1`. Likewise, in PureScript, ``10 `mod` 3 == 1``.
52+
53+
It's a bit harder to say what a 'remainder' operation should mean if we are trying to extend it to real (non-integral) numbers, though. Real numbers can be divided into one another with nothing 'left over', i.e. in some sense, the remainder of dividing one number by another is always 0.
54+
55+
Since JS just has one number type, it has to come up with a sensible way of handling cases where one or both of its arguments are non-integral. To address this, it uses a behaviour where it tries to find the largest *integer* multiple of the second argument which is smaller than the first argument, and then returns the difference between these. For example, in JS, `10.5 % 3 == 1.5`.
56+
57+
If this is the behaviour you want in PureScript, you should use `%` from the `Math` module in `purescript-math`. Its type is `Number -> Number -> Number` and it simply delegates to the `%` operator in JS.
58+
59+
However, PureScript's `Prelude` aims to provide a stronger theoretical foundation for common operators such as this one, which is why the `Prelude` exports a slightly different function, `mod :: forall a. EuclideanRing a => a -> a -> a`. For integers, `mod` works how you expect it to: ``10 `mod` 3 == 1``, just as before. However, for Numbers, `mod` always returns 0. This may be surprising; however, the reason it works this way is that it is based upon a mathematical structure called a *Euclidean Ring*, whose definition requires this behaviour. For more info, see the [EuclideanRing documentation](https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.EuclideanRing#t:EuclideanRing).

language/README.md

+6-7
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ The full language reference continues below:
3636

3737
1. [Types](Types.md)
3838
2. [Syntax](Syntax.md)
39-
3. [Values](Values.md)
40-
4. [Type Classes](Type-Classes.md)
41-
5. [Pattern Matching](Pattern-Matching.md)
42-
6. [Modules](Modules.md)
43-
7. [FFI](FFI.md)
44-
8. [Records](Records.md)
45-
9. [Differences from Haskell](Differences-from-Haskell.md)
39+
3. [Type Classes](Type-Classes.md)
40+
4. [Pattern Matching](Pattern-Matching.md)
41+
5. [Modules](Modules.md)
42+
6. [FFI](FFI.md)
43+
7. [Records](Records.md)
44+
8. [Differences from Haskell](Differences-from-Haskell.md)

0 commit comments

Comments
 (0)