Hacker News new | ask | show | jobs
by xrcyz 1070 days ago
> control flow is kind of... represented in data types

This sounds really interesting. Is there a toy example that comes to mind that you could share?

1 comments

Sure, a trivial one is:

`Either Int Char`

Example values of this type are: Left 3, Right 'a', Left -99, Right 'X'.

When we pattern match on a value of this `Either Int Char` type we have two branches to handle:

``` case myValue of

  Left someInt -> "It's an integer: " ++ show someInt

  Right someChar -> "It's a char: " ++ [someChar]
```

You can nest them if you need more branches: `Either Int (Either Char String)` and you can match out the different branches. Although people don't usually write code this way in Haskell: we usually think of better types that model what we're trying to do.

This is such a common way of doing things. There's a great function called, `compare` that returns a value of type `Ordering` which can be one of: LT, EQ, GT for each of the cases when comparing things with the usual comparison operators.

A lot of Haskell is variations on pattern matching: guards, if-expressions, etc.

Where this becomes even more useful is when you start to use types to enforce pre-conditions. I don't know how many times I've seen code in C++ or Python or Javascript where you have to validate the inputs to a function: make sure the list isn't empty otherwise throw an error! In Haskell we can prevent that possibility and eliminate the need for a useless check by writing a type for a non-empty list and use that in our function's signature (note: you can do this in C++ and Javascript too, it's a good idea).

Or you can write your type so that it fails in some way if the inputs are not right: use `Either SomeError Int`. Then your callers have to handle the error case and the happy case.

There are such things as "exceptions" in Haskell but they're limited (mostly) to things that happen in `IO` returning functions. There are ways to pick apart the seams of the GHC runtime and do nefarious things that would throw exceptions that would break the usual rules (eg: https://hackage.haskell.org/package/bytestring-0.10.8.1/docs...). However it's incredibly rare and sticks out like a sore thumb that it forces you to give such code extra scrutiny.

Exceptions aren't used for control flow in the same way that they are in Python, say. Handling them though is possible and a whole other topic. Let's just say it's a bit tricky to get used to... though Haskell has some good facilities for properly handling async/threads and exceptions so that resources are cleaned up and handled properly.