Live data from Hacker News

Use Your Type System

dzombak.com

201–210 of 357 posts

Re: Use Your Type System

#201

Earlier quoted context omitted.

> 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. Yes, that’s exactly the point. If you don’t know how to acquire an AccountID you shouldn’t just be passing a random string or UUID into a function that accepts an AccountID hoping it’ll work, you should have acquired it from a source that…

And that's my point: I'm usually getting AccountIDs from strings (passed in via HTTP requests) so the whole thing becomes a pointless exercise.

You just accept raw strings without doing any kind of validation? The step that performs validation should encode that step in the form of a type.

Re: Use Your Type System

#202
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…

This can usually be alleviated by structural types instead of nominal types.

You can always enforce nominal types if you really need it.

Re: Use Your Type System

#203

Earlier quoted context omitted.

Ada has this ability to define ranges for subtypes. I wish language designers would look at Ada more often.

Academic language designers do! But it takes a while for academic features to trickle down to practical languages—especially because expressive-enough refinement typing on even the integers leads to an undecidable theory.

Aren't most type systems in widely used languages Turing complete and (consequently) undecidable? Typescript and python are two examples that come to mind

But yeah maybe expressive enough refinement typing leads to hard to write and slow type inference engines

Re: Use Your Type System

#204

Earlier quoted context omitted.

Typescript's type system is turing complete, so you can do basically anything with it if this sort of thing is fun to you. Which is pretty much my problem with it: this sort of thing can be fun, feels intellectually stimulating. But the added power doesn't make coding easier or make the code more sound. I've heard this sort of thing called the "type puzzle trap" and I agree with that. I'll take a modern hindley milne…

>Which is pretty much my problem with it: this sort of thing can be fun, feels intellectually stimulating. But the added power doesn't make coding easier or make the code more sound. In practice nobody goes too crazy with it. You have a problem with a feature almost nobody uses. It's there and Range is like the upper bound of complexity I've seen in production but that is literally extremely rare as well. There is no…

I have definitely worked in TS code bases with overly gnarly types, seen more experienced devs spend an entire workday "refactoring" a set of interrelated types and producing an even gnarlier one that more closely modeled some real world system but was in no way easier to reason about or work with in code. The advantage of HM is the inference means there is no incentive to do this, it feels foolish from the beginning.

Re: Use Your Type System

#205
Go is a great language because it has distinct types by default, it's not about "making invalid states unrepresentable", it's about recording relationships about a particular type of value and where it can be used ie. it doesn't matter that UserID is just a string, what matters, is that now you can see what string values are UserIDs without making assumptions based on naming conventions.

Re: Use Your Type System

#207

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…

[deleted]

Re: Use Your Type System

#208

Swift has a typealias keyword but it's not really useful for this since two distinct aliased types with the same underlying type can be freely interchanged. Wrong code may look wrong but it will still compile. Wrapper structs are the idiomatic way to achieve this, and with ExpressibleByStringLiteral are pretty ergonomic, but I wonder if there's a case for something like a "strong" typealias ("typecopy"?) that indicat…

In what precise way are you envisioning that this would be different from a wrapper struct?

Pretty much only less boilerplate. Definitely questionable if it's worth the added complexity. And also it could probably be a macro.

Re: Use Your Type System

#209

Separate types for each model id is an extremely tedious way of avoiding bugs that can easily be prevented by a single test.

There are other benefits over a test.

The compiler tests the type is correct wherever you use it. It is also documentation.

Still have tests! But types are great.

But sadly, in practice I don't often use a type per ID type because it is not idiomatic to code bases I work on. It's a project of its own to move a code base to be like that if it wasn't in the outset. Also most programming languages don't make it ergonomic.

Re: Use Your Type System

#210

Separate types for each model id is an extremely tedious way of avoiding bugs that can easily be prevented by a single test.

Personally I like it, and it catches bugs right away, especially when there are multiple possible ids, e.g.

    func AddMessage(u UserId, m MessageId)
If it's just

    func AddMessage(userId, messageId string)
it's very easy to accidentally call as

    AddMessage(messageId, userId)
and then best-case you are wasting time figuring out a test failure, and worst case trying to figure out the bug IRL.

V.S. an instant compile error.

I have seen errors like this many times, both written by myself and others. I think it's great to use the type system to eliminate this class of error!

(Especially in languages like Go that make it very low-friction to define the newtype.)

Another benefit if you're working with any sort of static data system is it makes it very easy to validate the data -- e.g. just recursively scan for instances of FooId and make sure they are actually foo, instead of having to write custom logic or schema for everywhere a FooId might occur.

Post reply on HN