Publish boolean values post.

This commit is contained in:
Danila Fedorin 2020-08-21 23:06:26 -07:00
parent 6c3780d9ea
commit 06cbd93f05
1 changed files with 24 additions and 20 deletions

View File

@ -1,7 +1,7 @@
---
title: "How Many Values Does a Boolean Have?"
date: 2020-08-20T18:37:50-07:00
draft: ["Java", "Haskell"]
date: 2020-08-21T23:05:55-07:00
tags: ["Java", "Haskell", "C and C++"]
---
A friend of mine recently had an interview for a software
@ -38,12 +38,12 @@ in Haskell, and `1` and `0` in C. A boolean value is either true or false.
So, what's there to think about? There are a few things, _ackshually_.
Let's explore them, starting from the theoretical perspective.
### What's a Type, Anyway?
### Types, Values, and Expressions
Boolean, or `bool`, is a type. Broadly speaking, a type
is a property of _something_ that defines what the _something_
means and what you can do with it. That _something_ can be
several things; for our purposes, it can either be an
_expression_ in a programming language (in the form of `fact(n)`)
_expression_ in a programming language (like those in the form `fact(n)`)
or a value in that same programming language (like `5`).
Dealing with values is rather simple. Most languages have finite numbers,
@ -81,7 +81,7 @@ int meaningOfLife() {
No, wait, doesn't say "stack overflow" just yet. That's no fun.
And anyway, this is technically a tail call, so maybe our
C++ compiler can avoid growing the stack And indeed,
C++ compiler can avoid growing the stack. And indeed,
flicking on the `-O2` flag in this [compiler explorer example](https://godbolt.org/z/9cv4nY),
we can see that no stack growth is necessary: it's just
an infinite loop. But `meaningOfLife` will never return a value. One could say
@ -131,7 +131,7 @@ It turns out to be convenient -- formally -- to treat the result of a diverging
as its own value. This value is usually called 'bottom', and written as \\(\\bot\\).
Since in most programming languages, you can write a nonterminating expression or
function of any type, this 'bottom' is included in _all_ types. So in fact, the
set of possible values for `unsigned int`: \\(\\bot, 0, 1, 2, ...\\) and so on.
possible values of `unsigned int` are \\(\\bot, 0, 1, 2, ...\\) and so on.
As you may have by now guessed, the same is true for a boolean: we have \\(\\bot\\), `true`, and `false`.
### Haskell and Bottom
@ -173,7 +173,7 @@ They can then compile their program; the typechecker will find any mistakes
they've made so far, but, since the type of `undefined` can be _anything_,
that part of the program will be accepted without second thought.
The language `Idris` extends this practice with the idea of typed holes,
The language Idris extends this practice with the idea of typed holes,
where you can leave fragments of your program unwritten, and ask the
compiler what kind of _thing_ you need to write to fill that hole.
@ -185,8 +185,8 @@ really count as a value, since it's just a nonterminating
expression. What you're doing is a kind of academic autofellatio.
Alright, I can accept this criticism. Perhaps just calling a nonterminating
function a value _is_ far-fetched (even though denotational semantics
_do_ extend types with \\(\\bot\\)). But denotational semantics is not
function a value _is_ far-fetched (even though in [denotational semantics](https://en.wikipedia.org/wiki/Denotational_semantics)
we _do_ extend types with \\(\\bot\\)). But denotational semantics are not
the only place where types are implicitly extend with an extra value;
let's look at Java.
@ -195,13 +195,14 @@ core language level, any function or method that accepts a class can also take `
if `null` is not to that function or method's liking, it has to
explicitly check for it using `if(x == null)`.
Java's booleans are not, at first glance, classes. Unlike classes, which you have
This `null` value does not at first interact with booleans.
After all, Java's booleans are not classes. Unlike classes, which you have
to allocate using `new`, you can just throw around `true` and `false` as you see
fit. Also unlike classes, you can't assign `null` to a boolean value.
The trouble is, the _generics_ part of Java, which allows you to write
fit. Also unlike classes, you simply can't assign `null` to a boolean value.
The trouble is, the parts of Java dealing with _generics_, which allow you to write
polymorphic functions, can't handle 'primitives' like `bool`. If you want to have an `ArrayList`
of something, that something _must_ be a class.
But what if you really _do_ want an `ArrayList` of booleans? Java solves this problem by introducing
'boxed' booleans: they're primitives wrapped in a class, called `Boolean`. This class
can then be used for generics.
@ -219,7 +220,7 @@ Boolean myFalse = false;
Boolean myBool = null;
```
Beautiful, isn't it? And, unlike Haskell, where you can't _really_
Beautiful, isn't it? Better yet, unlike Haskell, where you can't _really_
check if your `Bool` is `undefined` (because you can't tell whether
a non-terminating computation is as such), you can very easily
check if your `Boolean` is `true`, `false`, or `null`:
@ -249,17 +250,20 @@ while(test) test -= 1;
This loop will run 255 times, thereby demonstrating
that C has at least 255 values that can be used
to represent the boolean `true`. There are other languages
with the notion of 'truthy' and 'falsey' values. However,
some of them differ from C in that they also extend this notion
to apply to equality. In JavaScript:
to represent the boolean `true`.
There are other languages
with this notion of 'truthy' and 'falsey' values, in which
something not exactly `true` or `false` can be used as a condition. However,
some of them differ from C in that they also extend this idea
to equality. In JavaScript:
```JavaScript
console.assert(true == 1)
console.assert(false == 0)
```
Then, there are still exactly two distinct values
Then, there are still exactly two distinct boolean values
modulo `==`. No such luck in C, though! We have 256 values that fit in `unsigned char`,
all of which are also distinct modulo `==`. Our boolean
variable can contain all of these values. And there is no
@ -269,7 +273,7 @@ respite to be found with `enum`s, either. We could try define:
enum bool { TRUE, FALSE };
```
But unfortunately, all this does is define `bool` to be a numeric
Unfortunately, all this does is define `bool` to be a numeric
type that can hold at least 2 distinct values, and define
numeric constants `TRUE` and `FALSE`. So in fact, you can
_still_ write the following code: