Live data from Hacker News

Use Your Type System

dzombak.com

21–30 of 357 posts

Re: Use Your Type System

#21

Type systems, like any other tool in the toolbox, have an 80/20 rule associated with them. It is quite easy to overdo types and make working with a library extremely burdensome for little to no to negative benefit. I know what a UUID (or a String) is. I don't know what an AccountID, UserID, etc. is. Now I need to know what those are (and how to make them, etc. as well) to use your software. Maybe an elaborate type sy…

To be fair, you probably needed to know that anyway? Or else you would've just passed invalid data into functions.

Re: Use Your Type System

#22
post #3

I like this. Very much falls into the "make bad state unrepresentable". The issues I see with this approach is when developers stop at this first level of type implementation. Everything is a type and nothing works well together, tons of types seem to be subtle permutations of each other, things get hard to reason about etc. In systems like that I would actually rather be writing a weakly typed dynamic language like…

FYI: Ruby is strongly typed, not loosely. > 1 + "1" (irb):1:in 'Integer#+': String can't be coerced into Integer (TypeError) from (irb):1:in ' ' from :168:in 'Kernel#loop' from /Users/george/.rvm/rubies/ruby-3.4.2/lib/ruby/gems/3.4.0/gems/irb-1.14.3/exe/irb:9:in ' ' from /Users/george/.rvm/rubies/ruby-3.4.2/bin/irb:25:in 'Kernel#load' from /Users/george/.rvm/rubies/ruby-3.4.2/bin/irb:25:in ' '

There seem to be two competing nomenclatures around strong/weak typing where people mean static/dynamic instead.

Re: Use Your Type System

#23

Type systems, like any other tool in the toolbox, have an 80/20 rule associated with them. It is quite easy to overdo types and make working with a library extremely burdensome for little to no to negative benefit. I know what a UUID (or a String) is. I don't know what an AccountID, UserID, etc. is. Now I need to know what those are (and how to make them, etc. as well) to use your software. Maybe an elaborate type sy…

To be fair, you probably needed to know that anyway? Or else you would've just passed invalid data into functions.

I cannot recall ever passing an invalid UUID (or long id) into a function due to statically-knowable circumstances.

Re: Use Your Type System

#24
Unfortunately, this can be somewhat awkward to implement in certain structural typed languages like TypeScript. I often find myself writing something along the lines of

  type UserID = string & { readonly __tag: unique symbol }
which always feels a bit hacky.

Re: Use Your Type System

#25
post #3

I like this. Very much falls into the "make bad state unrepresentable". The issues I see with this approach is when developers stop at this first level of type implementation. Everything is a type and nothing works well together, tons of types seem to be subtle permutations of each other, things get hard to reason about etc. In systems like that I would actually rather be writing a weakly typed dynamic language like…

Yep. For this reason, I wish more languages supported bound integers. Eg, rather than saying x: u32, I want to be able to use the type system to constrain x to the range of [0, 10).

This would allow for some nice properties. It would also enable a bunch of small optimisations in our languages that we can't have today. Eg, I could make an integer that must fall within my array bounds. Then I don't need to do bounds checking when I index into my array. It would also allow a lot more peephole optimisations to be made with Option.

Weirdly, rust already kinda supports this within a function thanks to LLVM magic. But it doesn't support it for variables passed between functions.

Re: Use Your Type System

#26
post #5

Does anyone know the term for this? I had "Type Driven Development" in my head, but I don't know if that's a broadly used term for this. It's a step past normal "strong typing", but I've loved this concept for a while and I'd love to have a name to refer to it by so I can help refer others to it.

Using basic types for domain concepts is called 'primitive obsession'. It's been considered code smell for at least 25 years. So this would be... not being primitive obsessed. It isn't anything driven development.

Different people draw the line in different places for this. I've never tried writing code that takes every domain concept, no matter how small, and made a type out of it. It's always been on my bucket list though to see how it works out. I just never had the time or in-the-moment inclination to go that far.

Re: Use Your Type System

#27
I've actually seen this before and didn't realize this is exactly what the goal was. I just thought it was noise. In fact, just today I wrote a function that accepted three string arguments and was trying to decide if I should force the caller to parse them into some specific types, or do so in the function body and throw an error, or just live with it. This is exactly the solution I needed (because I actually don't NEED the parsed values.)

This is going to have the biggest impact on my coding style this year.

Re: Use Your Type System

#28
post #3

I like this. Very much falls into the "make bad state unrepresentable". The issues I see with this approach is when developers stop at this first level of type implementation. Everything is a type and nothing works well together, tons of types seem to be subtle permutations of each other, things get hard to reason about etc. In systems like that I would actually rather be writing a weakly typed dynamic language like…

I've recently been following red-green-refactor but instead of with a failing test, I tighten the screws on the type system to make a production-reported bug cause the type checker to fail before making it green by fixing the bug.

I still follow TDD-with-a-test for all new features, all edge cases and all bugs that I can't trigger failure by changing the type system for.

However, red-green-refactor-with-the-type-system is usually quick and can be used to provide hard guarantees against entire classes of bug.

Re: Use Your Type System

#29
post #19

I was doing this and used it for a year in https://github.com/bbkane/warg/ , but ripped it out since Go auto-casts underlying types to derived types in function calls: Type userID int64 func Work(u userID) {...} Work(1) // Go accepts this I think I recalled that correctly. Since things like that were most of what I was doing I didn't feel the safety benefit in many places, but had to remember to cast the type in othe…

Yep in the same way it would allow `var u userID = 1` it allows `Work(1)` rather than insisting on `var u userID = userID(1)` and `Work(userID(1))`.

I teach Go a few times a year, and this comes up a few times a year. I've not got a good answer why this is consistent with such an otherwise-explicit language.

Re: Use Your Type System

#30
post #24

Unfortunately, this can be somewhat awkward to implement in certain structural typed languages like TypeScript. I often find myself writing something along the lines of type UserID = string & { readonly __tag: unique symbol } which always feels a bit hacky.

[deleted]
Post reply on HN