brandonspark
Joined 4 years ago
Joined 4 years ago
I agree with the high-level, though. I find that people (with respect to programming languages) focus far too much on the specific, nitpicky details (whether I use the `let` keyword, whether I have explicit type annotations or type inference). I find the global, project-level benefits to be far more tangible.
```ocaml
type 'a nonempty = Single of 'a | Cons of 'a * 'a nonempty
```
This would be the type of lists that contain one or more elements of the type parameter.
I think it's just convention that typically, when we talk about lists, we are interested in the empty case as well. Finding "all X that satisfy P in Y", as a general computational problem, is _very_ common (consider: filtering a list, querying for a predicate in a collection, finding sequences of moves in a search space), and generally could result in an empty list as a possible output.
In a non-practical sense, if you want the type theory, another reason is you can think of `[a]` as the free monoid on the collection of `a`. In other words, strings of elements of `a`, joined via concatenation. This monoid requires a unit, which is the empty list.
Though, I agree the semicolon delimiting is regrettable.
For instance, here's the SML code for it:
``` datatype exp =
Num of int
| Plus of exp * exp
| Minus of exp * exp
| Times of exp * exp
| Div of exp * exp
```Implement the function `eval : exp -> int`, which evaluates the expression as best as it can. Assume no division by zero.
Extra credit: Can you implement `eval' : exp -> int option`, that returns `SOME n` if the expression evaluates, and `NONE` if it divides by zero?