- 8 minutes
- The basic Boolean operators
!look much the same between the two languages.
||with things that aren’t Booleans; we’ll see what operators work with the
Maybetype to us do similar things in Haskell.
elseblocks and the “ternary”
elseplays the role of both of these.
And and Or (Booleans)
We start off very simply: The
> true && false false
> true || false true
λ> True && False False
λ> True || False True
The only difference you see here is that
False are capitalized in Haskell. The capital letters are important: This tells us that
False are data constructors.A term that starts with a capital letters in Haskell is necessarily a data constructor. (There are other things that start with capital letters, but they are all at the type level.)
false as built-in keywords in the language, in Haskell they are data constructors of an ordinary type named
The definition of the
Bool type in the standard library looks like this:
>>> !true false
>>> !false true
In Haskell we have a function called
not instead of an operator. The effect is much the same, though.
λ> not False True
λ> not True False
Just like we saw with
not is an ordinary function, not a language builtin. Its definition looks something like this:
|| operator isn’t just for Booleans; you can use it with any kind of value.
It returns the first argument if present (that is, truthy), and otherwise returns the second argument.
A common idiom is to apply a handful of
|| operators in sequence to select the first value that is present:
>>> null || null || 2 || 3 || null 2
This usage of
|| is quite similar to how we use the
<|> operator on
Maybe values in Haskell.
λ> Nothing <|> Nothing <|> Just 2 <|> Just 3 <|> Nothing Just 2
Haskell’s closest equivalent to the concept of “truthiness” and “falsiness” is the
Maybe type. Its definition looks like this:
Maybe type to introduce the possibility of the number being absent. In the example above, each
Nothing signifies the absence of a number (places where we used
null in JavasScript), and
Just 2 signifies the number
&& operator. It means something like this:
a && b && c, if all three values are present (that is, if they are all truthy), then the entire expression evaluates to the last of the values.
> 1 && 2 && 3 3
But if any of the values is missing (represented by a falsy value such as
null), then the evaluation terminates and the entire expression evaluates to a falsy value.
> 1 && null && 3 null
This usage of the
&& operator closely resembles the
*> operator on
Maybe values in Haskell.
λ> Just 1 *> Just 2 *> Just 3 Just 3
λ> Just 1 *> Nothing *> Just 3 Nothing
You can remember the meaning of
*> by thinking of it as an arrow pointing to the right, indicating that it discards the argument on the left and returns the argument on the right.There is a similar function
<* that does the opposite: it discards the right argument and returns the left argument.
else clause, and one using a
: ternary conditional expression.
Both of these forms of conditional have a Boolean condition, a branch for the true case, and a branch for the false case. The difference is that with
else, the branches are blocks, and the entire
else construct is a statement; it doesn’t evaluate to a value, it only produces some effect when it runs. With the
: form, the branches are expressions rather than blocks, and the entire
: construct is also an expression; it evaluates to a value, which we can then use as the argument to the
console.log function. Each form has a benefit and a limitation.
In Haskell, we don’t have to choose. When we translate these two examples into Haskell, both of them are written using an
putStrLn function application without needing to change which syntactic construct we used.