It is amazing what length people are willing to go in the hope of "safety".
Is there anybody out there who successfully build their own product, not via VC or other investments, but on their own time and own money who likes types?
To me it seems that types are something consultants and people who get paid for their time instead of their productivity like. Because it makes things more complex. So to achieve the same task, you can bill more time.
I have not seen anybody successfully build something on their own time, money, risk who like types. If there is someone here, I would love to see it!
On the other hand, I have seen many examples of lean code like the following turning into successful life style businesses and companies:
Quite an unusual take. There are millions of developers who prefer TypeScript over JavaScript for any job, including self-founded products.
But even if they didn’t exist, it’s a non sequitur. There are very good reasons for type systems regardless of how projects are founded.
You might not realize that Go has a very limited and awkwardly designed static type system that is the sole reason reason people prefer it for certain tasks over Python, which has both a dynamic, and by now an optional static type system.
Your final point, that types make things more complex and harder to develop is also flawed. Type systems exist to decrease the mental overhead and unload it from the programmer onto the compiler.
They might require more work upfront, but make software more solid, easier to reason about and easier to change. If you’re building a one-off that you will never change then a type less language might be of interest to you.
But it’s short sighted to think that you will be able to write it once and keep it running forever. Only managers who don’t code believe fairy tales like that. In reality many people sit down on a codebase, they fix things, and add functionality. When they do, they want to avoid bugs, they want the compiler to help them, they want LSP, they want to avoid null pointer dereference, double free, they want to be safer, and more productive.
They’d rather spend a week upfront instead of a day so that every one of the later changes takes a day instead of a week.
Also, types are a spectrum. C++ has types, Objective-C has types. Those alone have enough success stories to fill tomes! But of course you’re talking about strong static type systems like Haskell, Ocaml, Scala or ML, so you should read up on Jane Street. Or Mercury. Blockchains like Cardano.
Personally I think the onus is on you to prove that types are _not_ useful. Many of us enjoy types.
Pretty much all successful indie games use typed languages. Of course, there is a mix with untyped scripts in there too. But many only depends on typed languages.
You should watch this video [1] from Martin Odersky, creator of Scala.
It shows how the entire industry has moved towards stronger typing. Whether it's existing languages like JavaScript and Python or new ones like Rust and Swift. The trend is undeniable.
I use Scala and Rust every day and I personally think they are better for startups because they allow you to rely more heavily on the compiler to verify things rather than having to check at runtime with unit tests. That means more time on new features and less time fixing bugs and writing tests.
I don’t disagree on the summary of your post. Especially for refactoring, types can be great.
But it is funny you chose the creator of Scala as the example. The gold plated banana cables of typing. The entire language and its endless lang mailing list discussions is a meme by now.
1. A whole lot of programmers who didn't know how to use the language effectively in 2010. Less of an issue now the patterns are well established and industry wide the level of knowledge has increased (even Java has algebraic data types now)
2. Some idiots in the community, who have now left
3. Some rough edge cases in the Scala 2 type system; fixed in Scala 3
4. Ignoring the fact that not only language but also tooling is a significant factor affecting developer experience. Extremely long compile times, weird build system, lack of good IDE support.
5. Breaking backwards compatibility with each release. This is something that businesses care a lot about.
> 5. Breaking backwards compatibility with each release. This is something that businesses care a lot about.
This is a myth. Scala has had one significant compatibility break in 10+ years. Not even Java beats that. Meanwhile the likes of Python really do break compatibility every release, and businesses continue to use them.
I think people forget just how bad compatibility was a decade ago. The compiler promised no ABI compatibility even between minor versions, which on its own could have been fine; Go and Rust don't promise ABI compatibility either. The problem was that people still used maven and sbt for dependency management, which used binary dependencies, not source like Go and Rust.
So to get a Scala project going with several dependencies, you needed all of them to agree on a specific Scala compiler version and publish JARs built against it. If even one dependency lagged behind (and many often did), you couldn't update the compiler version for your project, locking you out of new versions of every Scala library you use.
This led to the ironic situation that it was easier to use Java JARs from Scala than to use Scala JARs. If the ecosystem had used source dependencies instead of binary dependencies, this could have been avoided, even if compile times may have been horrendous. Rust walks this tightrope steadily enough these days, and Go even makes it look easy.
Finally, even though the language didn't meaningfully break compatibility until Scala 3, the ecosystem as a whole did not respect backwards compatibility. For an example I'm sure many people here will remember viscerally, Lift Web kept making substantial backwards-incompatible changes regularly even after they knew they had commercial users who faced real-world costs for churn. Even the most foundational things like how to bind template elements to variables changed completely. Adding further insult, the documentation was not nearly up to the standard that would make migration productive even for those who could afford the churn.
I loved Scala but these factors burned me hard. It remains to be seen how Rust libraries will compare, but Go libraries have already proven backwards compatible to a fault, and both build dependencies from source so ABI is not an issue. I do however appreciate that Scala taught me that a beautiful language is not enough, real world usage requires responsible commitments from projects to users. It sounds like they've learned this, but a decade too late.
> I think people forget just how bad compatibility was a decade ago.
I think you're forgetting how long ago the issues were. It was pretty bad in the 2.7-2.9 days, but a decade ago was already into the 2.10 era.
> This led to the ironic situation that it was easier to use Java JARs from Scala than to use Scala JARs. If the ecosystem had used source dependencies instead of binary dependencies, this could have been avoided, even if compile times may have been horrendous.
I don't think that would've been worth it. Binary dependencies work great given that libraries cross-build; the real issue was back when source compatibility was broken often enough that that wasn't practical.
> For an example I'm sure many people here will remember viscerally, Lift Web kept making substantial backwards-incompatible changes regularly even after they knew they had commercial users who faced real-world costs for churn.
I don't think there'll be many remembering that. Lift was big, what, 15 years ago? It was already fading by the time I started Scala back in 2011.
That's just the thing, Scala and its ecosystem had these problems right at the height of its popularity, meaning that the situation was the worst right when the most people were around to experience it, and understandably many never looked back. Even if many individuals can look past it, it's become a very hard sell to teams.
It's the same story with any kind of merit vs trust. When you have a clean slate, you can build trust based on your merit, but once you break trust, merit alone isn't enough to win it back. In this industry in particular, far too many other options are already holding and building trust.
I truly wish Scala had indeed become the mainstream industry language instead of say Go. I hope Rust polishes off its rough edges and succeeds where Scala failed and where Go doesn't go far enough. But I don't see any future where Scala regains industry relevance, not even if both Go and Rust self-destruct as well.
Meh. OCaml spent over a decade underappreciated, fixed a few sticking points like package management, and then underwent a resurgence. I'd like to think that merit will ultimately win through.
No, I meant binary compatibility. Upgrading to a newer version always required recompiling all dependencies. One dependency didn't get an update and you were essentially locked on the old version. Some projects took years to upgrade from 2.11 to 2.12 and then 2.12 to 2.13 e.g Spark. This was a real pain for us.
Source compatibility based model would be ok if Java/Scala build systems worked like Cargo/Go/Npm and compiled dependencies from sources. However, that would make compile times orders of magnitude worse, and they were already unacceptable without it. I remember our project that had about 30k lines of Scala and 300k lines of Java took about 7-12 minutes to build from scratch (and the biggest contributor of compile time was scala). And we didn't even use advanced and slow stuff like macros or typelevel programming. I remember we were seriously looking into stuff like keeping the compiler in memory between the runs (thanks Bloop) and that made it much better although it came with it's own set of new problems.
Comparably on the same (now outdated) hardware Rustc is able to compile 500k lines of all dependencies in about 28 seconds (including linking).
> One dependency didn't get an update and you were essentially locked on the old version. Some projects took years to upgrade from 2.11 to 2.12 and then 2.12 to 2.13 e.g Spark. This was a real pain for us.
Spark is a special case though - it really was just Spark, and you can't really compare that to something like Rust where as far as I know there's no equivalent. Everything else that was maintained at all put out cross-builds very quickly once the changes between versions got to be small.
On the contrary, the power of Scala types means you are less likely to get in a case where the compiler blocks you despite your code being safe.
See the example of the article, where you don't have covariance in Go and the compiler fails. Same in Java where you have to cast (and add unsafety) to make the compiler accept your code.
In Scala when using immutable structure (the default) you have covariance and the compiler will happily let you call a function that takes a List[A] with a List[B] if B extends A.
Now that's true that you can do overly complex things with Scala types, but you don't have to.
I love type safety. When I drop down to a dynamically typed language I'm actually slower as I have to double check my work. I don't understand how someone in 2023 can be against type safety.
Yes, as everyone knows, you are only entitled to an opinion about software if you are also a successful business entrepreneur without external funding.
Good type systems increase velocity by leaving less room for error, so that you don't have to waste half your time debugging and fixing issues that could have been easily prevented. They also provide helpful structure and an IDE experience (the right values, functions, actions, etc are actually suggested for you wherever you are) that really does speed up development a lot.
There's of course always a trade-off: bad type systems can get in your way with boilerplate that you have to wrangle. But I don't think that's the typical experience.
> Yes, as everyone knows, you are only entitled to an opinion about software if you are also a successful business entrepreneur without external funding.
That's not it. I disagree with the GP, but they do have a point: coding for pay, coding for fun, and coding for your own business are all markedly different. So the question whether something works or not in one of those contexts is a valid one.
I disagree with conclusion, though. Successful products are written in whatever the authors know intersected with whatever will get the job done. If you're Chuck Moore and work on embedded stuff, you'll use Forth and will be hugely successful, running circles around your competitors who use C. The relative strengths of a static type system vs unityped language are more than offset by familiarity and experience of the authors.
The story changes a bit when your product grows and you need to hire a larger team of people to work on it. The benefits of a static analysis become more pronounced when the codebase gets bigger. However, if you somehow luck out and get a team of highly competent people, they will use whatever mechanisms are available to make your larger codebase still tractable, even if they use Lisp, PHP, or PERL.
You can bet on something that explodes (Windows Phone...) and then your product gets done in by the choice of tech. Outside of those cases, though, the tech doesn't matter that much. Whatever you do, you'll have problems. Going for a really powerful language will severely limit your choice of libraries. Going with the most common language will leave you fighting decades of accrued nonsense. Going with statically typed language (without sane macros) will lead to lots of boilerplate code and will severely limit what you can do on runtime with the code (unless you use reflection, but then you're back to untyped land). Going with unityped/untyped language will make you hunt the inter-dependencies between your modules and you'll likely become conservative with removing old code (and other forms of refactoring) as a result.
Finding a right trade-off for a tech for your product is never about a single feature of that tech. It's about a complex interplay of what you have, what you think you can get, and what you want to do.
My shell (interactive command line environment + scripting language) is written in a type safe language. It’s tens of thousands of lines of code (maybe even hundreds of thousands, I’ve not counted) and has been actively developed for the best part of a decade.
I’d have completely failed at this project if it weren’t for type safety because refactoring anything that long lived and that much code would have been a nightmare.
So there was no risk involved like "Will I tank my future if this fails?".
What I witnessed is that makers who are willing to bet on something with real consequences dislike types as they slow down the progress and therefore the chances of success.
Why don’t _you_ come up with examples where non-VC funded but successful businesses are doing well in part because they chose to ignore types?
At this point, I’m not even sure what you are trying to prove and I’m starting to feel that whatever it is, you’re trying to prove it to yourself mostly.
I took the comma in your comment to mean “or” rather than “and”. You’re right. It’s not a business. But I am risking my own time (you could argue that time is money :P)
Your point is pretty daft though. If was relevant to self-funded startups then it would be relevant to VC funded startups and hobby projects as well. But the fact that you’re having to dismiss all these counter examples people present demonstrates that your point is wrong and you’re simply not willing to back down from your position.
Plus there’s been a wealth of companies founded on .NET and Java technologies that are older than some people on here have been alive. So it’s not like examples don’t exist. You’re not just receptive to them.
Your non-typed code still uses types, you just have to remember what they are and test functions in more ways to check that your memory and assumptions are correct.
Exactly. If not, any variable is just binary data, and has no basis for interpretability. Any program with a single branch instruction at the assembly level, has implicit types!
I see a TON of open source projects (frameworks, libraries etc.) on the frontend alone that are built using TypeScript. And on the backend Golang is hugely popular and Rust is gaining a lot of traction. All in open source. Not every one of those open source projects is backed by VC money or built by consultants.
> I have not seen anybody successfully build something on their own time, money, risk who like types. If there is someone here, I would love to see it!
Experiment: you go and search for people who have built something on "their own time, money, and risk". Find them by what they've built. First decide whether you respect what they've made, and only then check what language they decided to use to build the thing. I predict that you'll find plenty of people who have built respectable things using typed languages.
C# is my language of choice and the strong typing allows me to refactor and change names of (“internal”) things at a whim on even extremely large solutions with no possibility of runtime failures due to the refactoring tooling doing all the work for me and the compiler complaining if something doesn’t line up.
My view is that people who don’t like strongly typed languages have either just never worked on very large codebases, or they avoid refactors due the general impracticality of it, or they have loads of unit tests to catch runtime “type mismatches” which would have just been caught by the compiler in a strongly typed language.
Choosing an untyped language vs a typed one is a trade off of less upfront work in typing things vs future analysis capabilities of your code. And for me, the upfront cost of typing things is negligible compared to the gains for the future, which in my decade+ of experience pays itself many many times over on any non trivial sized code base.
Some languages are weakly typed though, which can cause confusion at the points where one type is automatically converted to another (e.g. JS, where 1 + "2" = "12"), and you need to keep type conversion and precedence in mind.
It didn't take long earlier in my career to realize that in JS, you need to be aware of the type of your variables and try and avoid any implicit type conversions.
I worked on a large JS app some years ago, before types came to that world. It worked, but only because I had a good memory of what fields and types there were (JS has types, they're just hidden and weak).
But my memory, my individual ability to keep code in my head, to keep an API's datatypes in my head, or to keep function signatures in my head does not scale. Second, it's not reliable, and needs either tests or production errors to verify.
Untyped / weakly typed languages aren't going to go away, and if you prefer them, I'm not going to convince you otherwise. I don't mind them for smaller projects or one off scripts either, utilities. But for larger applications that multiple people are involved in (directly or indirectly, e.g. an API not maintained by myself), I prefer to have a strong type system.
That said, I don't think Go's type system isn't the best, it's kinda loose in some cases (e.g. no enum types). You can't use it to bolt down your application as tightly as e.g. Java or Scala or other such languages. That's probably by choice though, since you need to stay productive as well and not masturbate over your own type system.
>Is there anybody out there who successfully build their own product, not via VC or other investments, but on their own time and own money who likes types?
Only almost every small app software house for Windows and MacOS ever, and almost evert indie game developer?
And anybody who wrote and sells of supports and makes money as FOSS, any libraries/backend tools/etc in C++ and co, so tens of thousands of projects?
Types are like a built-in test suite for your code. They constantly check that what you are doing is not nonsensical.
If you want a high-profile story, take Figma; it's built with C++ which is a highly type-oriented language.
Anecdotally, in the last three startups I worked (including one really tiny), the code base was / is largely in Typescript, Kotlin, Python with heavy type annotations, and small bits of Rust.
I don't agree with your comment in general, but I think I understand where you're coming from. Many formerly loosely typed languages (JS, PHP, Python etc.) have tried to introduce stronger typing - I have the most experience with PHP, so I'll talk about that: sometimes "stronger" typing can be a pain, especially if you try to introduce it to an existing weakly typed project, or if you're interfacing with some other weakly typed system (e.g. JSON files). One example: everything is working fine, then you declare a function parameter as `string`, and suddenly you get runtime errors because one of the many callers occasionally passes `null`, and you forgot the question mark before the `string`.
So what you’re saying is that by introducing type checks, you’re actually uncovering bugs. Seems to me like proof of value right there.
What does surprise me is that adding types to your PHP code adds _runtime_ errors. With Python, type annotations are predominantly used by static typecheckers and are ignored at runtime (except from some libraries like FastAPI that use reflection to inspect the type annotations). I always assumed all dynamically typed languages that introduced explicit types worked the same way
> What does surprise me is that adding types to your PHP code adds _runtime_ errors
There are static analysers for PHP too, but yeah they’re also enforced at runtime.
I think I prefer that, if there’s going to be a non-zero risk of bad types landing in production code, I’d prefer that be an error than for it to just carry on and potentially fail later in strange ways.
That said, one of the reasons cited for PHP not having generics is the performance cost of runtime enforcement. So there are a few people out there now making the case for a generic syntax that is ignored at runtime, but that can be built into static tooling. Which I can get behind—PHPs type system is really not bad at this point, but generics would be really nice.
Well no, maybe there was a legitimate reason to pass null instead of a string (I mean, nullable types exist for a reason), and then you just introduced a bug because you didn't look hard enough at all the places your function is called (which can take some time).
If you have a null-aware type system, then you just can’t call your function with a null, so no bug?
Also, if you just annotated the same implementation that already didn’t handle nulls properly, how is it any different? Your code would just die at runtime a few lines later, with a less explicit errorz
Yes, me. I develop an IDE for Clojure code which is a mix of Clojure and Kotlin. I like both, but what I like about Clojure is the interactive programming, not the lack of types. If there were a statically typed Clojure I’d be all over it.
There's no Typed Clojure, still? I seem to remember people porting Typed Racket to Clojure; a quick search gives me core.typed[1] and typedclojure[2]. There's an example[3] looking like this:
(t/ann hello-world-error [t/Int :-> t/Str])
(defn hello-world-error [a] (inc a) ;#"Simplified a bit")
(both definitions are rejected at compile time; in Racket, it works in the REPL, too, not sure about Clojure)
...and Typed Racket is a really powerful type system (see refinement types[4]). So, I thought it's just a matter of time for Clojure to get to that level of power and support. It should be much easier to do this to Clojure than to Ruby, given that you have a working example of how to do it well. So I'm really surprised Clojure isn't gradually typed by now, with most of the code being annotated and type-checked at compile time.
Typed Clojure is still a thing and I think Ambrose is still working on it, but I don't think anyone actually uses it in practice. A few companies tried it and then backed it out, but that was a while ago now. It may be better recently but I haven't made the time to really kick the tyres on it to see what's changed. Previous it was just a pain ergonomically.
Hmm, that's sad. I guess the difference with Typed Racket is that the Racket devs and researchers behind it were all completely sold on the idea from day one, which resulted in a quick progress in annotating the whole of the stdlib. Without that, you'd need to annotate everything you require (import) yourself, which would be a massive pain. Another difference might be the module system of Racket, which is pretty unique. IIRC Clojure modules are just namespaces, similar to CL, right? In Racket, the module system along with the extensive support for contracts, allowed TR to be much more strict with types, while still interfacing well with untyped code. In effect, Racket as a whole is gradually typed, but within the bounds of TR modules there's a sound, fully static type system.
It's a shame. I thought Clojure, as the only Lisp currently used in the industry, would benefit from the great work of Racket folks the most. After all, static typing in your pet project is much less important (or even desirable) than in a production-quality software made by a team of devs under time constraints. It's strange to see JavaScript and Python getting (widely used) gradual type systems before Clojure when the foundational work on gradual type systems was done in Lisps (Scheme and Racket).
Types, like many things in life, only matter once you are in a situation where you could really use them(or would sidestep a certain kind of problem…) If you are in one of those, and more importantly don’t realize it, that is when you really pay. The daily languages that we all use(99% of us) do not utilize complex type systems and thus cannot solve complex problems.
Is there anybody out there who successfully build their own product, not via VC or other investments, but on their own time and own money who likes types?
To me it seems that types are something consultants and people who get paid for their time instead of their productivity like. Because it makes things more complex. So to achieve the same task, you can bill more time.
I have not seen anybody successfully build something on their own time, money, risk who like types. If there is someone here, I would love to see it!
On the other hand, I have seen many examples of lean code like the following turning into successful life style businesses and companies:
https://gist.github.com/nikcub/3833406