

Practical Benefits of the Haskell Type System - mightybyte
http://mechanical-elephant.com/thoughts/2015-08-10-the-pratical-benefits-of-haskell-typesystem/

======
AnimalMuppet
A bit off topic, but this seems like as good a place to ask this as any I've
seen lately.

Is it just me, or is there a huge hole in Haskell's type systems around
dictionaries and tuples?

If I understand correctly, if you want to do something like a C/C++ struct (a
collection of data fields, not a class with some behavior), then in Haskell,
you either make it a dictionary with string keys, or you make it a tuple. But
if you pass either of those to a function, don't you lose type safety?

Let's say that I have a structure that represents a person. It's got a first
name (string), a last name (string), and an age (non-negative integer). I
create a tuple (first, last, age), or I create a dictionary ("first" : first,
"last" : last, "age" : age). (The syntax there is lousy, I don't know how
Haskell has you assemble a dictionary. It's intended to be read as ("key" :
value) entries.)

My function can require that it gets passed a tuple. I suspect that it can
require that it gets passed a tuple with three items. But can it require that
it gets passed a tuple that is (string, string, integer)? Worse, can it
require that it gets passed a tuple that is (first, last, age) and not (city,
state, zip code)?

Dictionaries are even worse. The function may be able to require that it gets
passed a dictionary with three entries. But can it guarantee that it gets
passed a dictionary with a "first" key, and that the value of that key is a
string?

So it seems to me that C/C++ _in this area_ can give you stronger type safety
than Haskell, because a function can guarantee that it got passed a Person
struct, which has a string first, and a string last, and an int age, and that
it did not get called with anything else.

Or am I all wet, and only an idiot would try to do structs that way in
Haskell?

~~~
samungo
Yes that would be a bad way to do structs in Haskell. Instead you would simply
use Haskell's record syntax, ie. data Person = Person { firstName :: String,
lastName :: String, age :: Int }

You could also easily define more specific types like for example: type Age =
Int, which should prevent somebody from creating a person where they use a zip
code for that person's age.

~~~
mightybyte
I'll second this comment. No self respecting Haskell programmer would use the
tuple or dictionary scheme described. This is exactly how you'd expect to see
it done in Haskell.

    
    
        data Person = Person
            { firstName :: String
            , lastName  :: String
            , age       :: Int
            }
    

The compiler automatically creates the following functions for you.

    
    
        Person :: String -> String -> Int -> Person
        firstName :: Person -> String
        lastName :: Person -> String
        age :: Person -> Int
    

So you get all the expected type safety. The nice thing is that since this
syntax is very light, you end up creating all kinds of small types here and
there for better type safety. Whenever I find myself using tuples of more than
3 or so items, I'll frequently create a new type for it. This serves as better
documentation and makes the code easier to refactor.

