Live data from Hacker News

Use Your Type System

dzombak.com

131–140 of 357 posts

Re: Use Your Type System

#131

This in an usage of Value Objects as defined in DDD https://en.m.wikipedia.org/wiki/Value_object Also relevant https://refactoring.guru/smells/primitive-obsession

Came here to say this. This is an old thing. I’m guessing next we’ll rediscover “Stringly Typed”?

That refactoring guru raccoon reminds me of Minix for some reason.

Re: Use Your Type System

#132
post #127

In TypeScript you can enable this by using BrandedTypes like this: type UserId = string & { readonly __tag: unique symbol }; In Python you can use `NewType` from the typing module: from typing import NewType from uuid import UUID UserId = NewType("UserId", UUID)

In Python 3.12 syntax, you can use

    type UserIs = UUID

Re: Use Your Type System

#133

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…

Yeah, most languages I've used are like this. E.g. rust/c/c++. I guess the examples in TFA are golang? It's kind of nice that you don't have to define those wrapper types, they do make things a bit more annoying. In C++ you have to be extra careful even with wrapper classes, because types are allowed to implicitly convert by default. So if Foo has a constructor that takes a single int argument, then you can pass an i…

Rust has the newtype idiom which works as proper type alias most of the time

Re: Use Your Type System

#134
post #25

Earlier quoted context omitted.

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 ch…

The generic magic for this is called “dependant types” I believe - generics that can take values as well as types as parameters. Idris supports these

The full-blown version that guarantees no bounds-check errors at runtime requires dependent types (and consequently requires programmers to work with a proof assistant, which is why it's not very popular). You could have a more lightweight version that instead just crashes the program at runtime if an out-of-range assignment is attempted, and optionally requires such fallible assignments to be marked as such in the code. Rust can do this today with const generics, though it's rather clunky as there's very little syntactic sugar and no implicit widening.

Re: Use Your Type System

#135

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…

This sounds elegant in theory but very thorny in practice even with a standards change, at least in C++ (though I don't believe the issues are that particular to the language). Like how do you want the equivalent of std::cout << your_different_str to behave? What about with third-party functions and extension points that previously took strings?

Re: Use Your Type System

#136
post #15

Hard not to agree with the general idea. But also hard to ignore all of the terrible experiences I've had with systems where everything was a unique type. In general, I think this largely falls when you have code that wants to just move bytes around intermixed with code that wants to do some fairly domain specific calculations. I don't have a better way of phrasing that, at the moment. :(

Maybe I know what you mean.

There are cases where you have the data in hand but now you have to look for how to create or instantiate the types before you can do anything with it, and it can feel like a scavenger hunt in the docs unless there's a cookbook/cheatsheet section.

One example is where you might have to use createVector(x, y, z): Vector when you already have { x, y, z }. And only then can you createFace(vertices: Vector[]): Face even though Face is just { vertices }. And all that because Face has a method to flip the normal or something.

Another example is a library like Java's BouncyCastle where you have the byte arrays you need, but you have to instantiate like 8 different types and use their methods on each other just to create the type that lets you do what you wish was just `hash(data, "sha256")`.

Re: Use Your Type System

#137
post #15

Hard not to agree with the general idea. But also hard to ignore all of the terrible experiences I've had with systems where everything was a unique type. In general, I think this largely falls when you have code that wants to just move bytes around intermixed with code that wants to do some fairly domain specific calculations. I don't have a better way of phrasing that, at the moment. :(

Ideally though, the compiler lowers all domain specific logic into simple byte-moving, just after having checked that types add up. Or maybe I misunderstood what you meant?

Re: Use Your Type System

#138
post #74

Earlier quoted context omitted.

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 ' '

Good luck with this fight. I've had it on HN most recently 7 months ago, but about Python: https://news.ycombinator.com/item?id=42367644 A month before that: https://news.ycombinator.com/item?id=41630705 I've given up since then.

I already wrote about wrt Elixir: https://arrowsmithlabs.com/blog/elixir-is-dynamically-and-st...

Re: Use Your Type System

#139

I've seen experienced programmers do this a lot. It's the kind of thing that someone thinks is annoying, without realizing that it was preventing them from doing something incorrect.

It can be annoying though. I think Rich Hickey has a point that bugs like this almost certain get caught by running the program. If they make it into production it usually results in an obscure edge case. I’m sure there are exceptions but unless you’re designing for the worst case (safety critical etc) rather than average case (web app), types come with a lot of trade offs. I’ve been on the fence about types for a lo…

An engineer getting up to speed on a 10 year old web app that uses dynamic types will likely have a very different opinion.

No types anywhere, so making a change is SCARY! And all the original engineers have usually moved on. Fun times. Types are a form of forced documentation after all, and help catch an entire class of bugs. If you’re really lucky, the project has good unit tests.

I think dynamic typing is wonderful for making software quickly, and it can be a force multiplier for startups. I also enjoy it when creating small services or utilities. But for a large web app, you’ll pay a price eventually. Or more accurately…the poor engineer that inherits your code in 10 years will pay the price. God bless them if they try to do a medium sized refactor without types lol. I’ve been on both ends of the spectrum here.

Pros and cons. There’s _always_ a tradeoff for the business.

Post reply on HN