Earlier quoted context omitted.
This must be strictly an old school Valley problem. Up in the city, IDEs are standard. How would you even write Scala at Twitter without an IDE?
How, you ask? https://scalameta.org/metals/docs/editors/emacs/
The type system is a programmer's best friend
431–440 of 467 posts
Re: The type system is a programmer's best friend
#432This is, IMvHO, such old news that it feels... weird to still read about it in a year with the prefix of 20. Every programmer who has ever single-handedly written a 100,000+ LOC software system will tell you the same thing: shift as much responsibility on the compiler as you can and have the compiler check the code you write to any extent technologically possible. Getting rid of bugs by experiencing, diagnosing and f…
> (Yes, Rust 4ev3r! ;)) Rust has a perfectly nice type system by modern standards, but it's nowhere close to showing you just how deep the rabbit hole goes when it comes to avoiding bugs at runtime by having stronger type systems. For example suppose my Rust function takes a slice of clowns (named unimaginatively "clowns") and also a usize integer k. Can we write clowns[k] ? Rust says sure, it will emit a runtime bou…
I disagree -- Rust's type system is pretty weak and very limiting compared to other modern languages like Typescript, Nim, Zig, or even C++. That's without even without getting into dependent type languages.
There are so many basic patterns which Rust's type system can't handle, especially when it comes to compile time types. For example, one recent thing I ran into was trying to downcast a dyn Trait into another more specific dyn Trait. It's just not possible, at least on stable. Instead you have to do ugly work like getters that return sub-traits wrapped in optionals. Ick, the visitor pattern was easier.
Rust's type system philosophically takes a very strict "closed system" approach too. Meaning one can only really write code that's valid for every known instance. This limits entirely valid and useful subset of programs to programmers using libraries or language features. I'm not talking about runtime dynamism, but compile time dynanism. C++ with concepts provides a much more powerful and adaptive type system.
Programming in Rust frustrates me that I can't do any of the compile time checks that I've become accustomed to doing in other languages. It makes doing them at runtime difficult as well.
> but it's nowhere close to showing you just how deep the rabbit hole goes when it comes to avoiding bugs at runtime by having stronger type systems.
Totally agree on that! Though that's missing how powerful compile time programming in general can be even without the dependent types. Personally I'm excited to see how C++ Concepts can evolve. Though I'm not sure how much that starts overlapping with Dependent Types.
Re: The type system is a programmer's best friend
#433Earlier quoted context omitted.
Again, I was referring to user defined types (not primitive types), which are not classes.
> A class specified by the keyword class, is a user defined type that contains both data members and member functions... http://www.cs.fsu.edu/~cop3014p/lectures/ch8/index.html
module Example
type mytype
val id: mytype -> mytype
end = struct
type mytype = {
position:(int * int)
}
type othertype = int
let id self = self
end
```How many classes I have defined? Exactly zero. How many types I have defined? Definetely not zero. One of these types is secretly equivalent to a primitive type, while the other is not, and none of this is known to users of these types.
I am not sure why keep trying to show "class = type". It is wrong, those are different concepts. I don't care what c++ says
Re: The type system is a programmer's best friend
#434Earlier quoted context omitted.
I don't know Haskell, but in the typescript code the types aren't doing anything... sendToEmail sends to any kind of Email. And if the code wants to know if an Email is verified, it inspects the verified field. > Of course they do - they tell you that the bug is in the verification code, and not in any of the thousands of lines of business logic separating it from the place where the error was found. Whether you cent…
> sendToEmail sends to any kind of Email. That's my point, you don't need a combinatorial explosion of behaviors for every possible most-specific-type, you can just reuse existing ones. > And if the code wants to know if an Email is verified, it inspects the verified field. That's exactly what you shouldn't do. Runtime "type" inspection is just bad overly distributed parsing. The point of typing is to move errors to…
You've got to understand: Whether or not a particular email address is verified or not isn't something that's generally known at compile time... That means compile time checks cannot actually guarantee if that email address is verified or not.
The compiler cannot know something that isn't known. There must be runtime code somewhere doing the check.
What people are really talking about with types here is that if you organize your code in a certain way, you can put the code that verifies whether an email address is verified or not in one place and use types to help make sure other code doesn't accidentally ignore or change that guarantee.
That's good and fine. But... (1) you can do the very same thing without types; (2) Either mechanism is only as good as your code organization and controls that ensure there's a single place this is determined (and that that place is correct).
Re: The type system is a programmer's best friend
#435Articles like this bug me. You've given me a list of why types are awesome. Great. Now, tell me what the tradeoff is. Nothing is free in engineering. To get something, you have to give up something else. Even grug[0] understands this. [0]: https://grugbrain.dev/#grug-on-type-systems
> Nothing is free in engineering. To get something, you have to give up something I think this is a dangerous position to take to extremes/as an axiom. Not talking about type systems at all here. The assumption that, given two tools/techniques for accomplishing the same goal, there are always equivalent tradeoffs simply isn't true. Some tools are better than others. That statement usually provokes misinterpretation.…
The issue is that people from one side will always downplay the tradeoffs (or pretend they don't exist, like the current author). This exactly how hype and cargo culting happens.
Re: The type system is a programmer's best friend
#436Earlier quoted context omitted.
> sendToEmail sends to any kind of Email. That's my point, you don't need a combinatorial explosion of behaviors for every possible most-specific-type, you can just reuse existing ones. > And if the code wants to know if an Email is verified, it inspects the verified field. That's exactly what you shouldn't do. Runtime "type" inspection is just bad overly distributed parsing. The point of typing is to move errors to…
> The point of typing is to move errors to compile-time. You've got to understand: Whether or not a particular email address is verified or not isn't something that's generally known at compile time... That means compile time checks cannot actually guarantee if that email address is verified or not . The compiler cannot know something that isn't known. There must be runtime code somewhere doing the check. What people…
Yes, obviously. What is knowable at compile time is the stuff that comes after: given that the input to this function has property X, does the output have property Y? Arguments, not premises.
> But... (1) you can do the very same thing without types
Sure, and if someone makes an SMT-solver-oriented language (that isn't just using it to drive type inference) I'll be happy to try it out. But what most people who dislike types claim is that you can replace them with testing (true in principle, false in practice: no one actually remembers to test every last edge case every single time) or just programmer discipline (lol).
Re: The type system is a programmer's best friend
#437Earlier quoted context omitted.
> Unit tests are a breeze since I never have to cast objects or worry about generics Generics reduce the amount of things you must care about on your tests. And you shouldn't cast objects in almost no code ever. Most 100k LoC programs won't need it even once, your microservices should need it proportionally less. That's the thing. The gains grow superlineraly with the amount of code. They make it just a bit easier to…
"And you shouldn't cast objects in almost no code ever." - I have a question about tests. Imagine I want to test a function that operates on quite large application state but not all app state is necessary for that function. Options: - Define all app state as a snapshot. Problem: snapshot can become stale, so more infra might be necessary to make sure that snapshot is up to date; - Pass only the necessary state and c…
If not all app state is necessary for that function, it shouldn't require the whole app state in its arguments.
type AppState = { databaseConnection: DatabaseConnection, env : "dev" | "prod", apiToken: string, userId: string, ... } & SomeOtherStuff
const dropTables = (app: Pick & {env: "dev"} ) => app.databaseConnection.dropTables()
Conversely, if a function you don't control says it needs the whole app state, believe it.Re: The type system is a programmer's best friend
#438Earlier quoted context omitted.
GC is not just for memory leaks, but memory safety in general. It also enables several paradigms that are extremely difficult to get right without memory safety. In order to have a proper comparison, you should control for variables that are irrelevant to the experiment. In this case, you want to look at the effect of typing, so you should control for GC. Which is why you should compare python to other GC'd static la…
>GC is not just for memory leaks, but memory safety in general. No this is not true. Memory safety and memory leaks are different concepts. You can trigger a memory leak without violating memory safety. In fact a memory leak is not really an error recognized by an interpreter or a compiler or a GC. It is a logic error. A memory leak is only a leak because you interpret it as a leak. Otherwise the code is literally do…
Re: The type system is a programmer's best friend
#439Earlier quoted context omitted.
> (Yes, Rust 4ev3r! ;)) Rust has a perfectly nice type system by modern standards, but it's nowhere close to showing you just how deep the rabbit hole goes when it comes to avoiding bugs at runtime by having stronger type systems. For example suppose my Rust function takes a slice of clowns (named unimaginatively "clowns") and also a usize integer k. Can we write clowns[k] ? Rust says sure, it will emit a runtime bou…
> Rust has a perfectly nice type system by modern standards I disagree -- Rust's type system is pretty weak and very limiting compared to other modern languages like Typescript, Nim, Zig, or even C++. That's without even without getting into dependent type languages. There are so many basic patterns which Rust's type system can't handle, especially when it comes to compile time types. For example, one recent thing I…
So, C++ 20 Concepts is basically what Bjarne Stroustrup proposed for a future version of his C++ language in the early 2000s. Several people proposed and WG21 accepted, a far more capable feature set for Concepts, this is often referred to as C++ 0x Concepts, since it was accepted for C++ 0x, the standard that would eventually (after years of delays) become C++ 11.
Bjarne wrote a paper arguing that this more powerful feature set was unnecessary and perhaps unworkable, and WG21 wound up removing Concepts from C++ 11 entirely (and the people behind it mostly got the message and ceased working on C++ altogether). A decade later, something that's close to Bjarne's original proposal became a C++ 20 feature.
C++ 0x Concepts was similar to Rust's Trait system in many ways. Particularly notable features of C++ 0x Concepts you might recognise in Rust's Traits:
1. Third parties can implement a C++ 0x Concept for some type which was not originally conceived with this Concept in mind, they just write the implementation and it works.
2. C++ 0x Concepts must be explicitly implemented they're not just a syntactic requirement that could be satisfied by happenstance in a type which is not in fact suitable.
3. As a result of 1 & 2, the C++ 0x Concepts have Semantics which in C++ 20 Concepts are confined to the idea of "modelling" a Concept or else IFNDR.
Re: The type system is a programmer's best friend
#440Earlier quoted context omitted.
People using dynamic languages deeply, especially library and framework authors, regularly write abstract/generic code for which a suitable type declaration would be mind-bendingly difficult in a very sophisticated type system and impossible in a weak one. You can argue that this is ill-advised! But static typing with normally-powered type systems leads to more voluminous and more purpose-specific code. Very powerful…
Can you provide a concete example? If you do, I am sure Rust/C++/C/Java/C# programmers can show you how to implement in their language.