This is not good. One of the author's arguments is that type inference in an IDE is bad because sometimes I read code in a book where I don't have type inference...
I don't know about other folks, but the vast majority of code I read is in my editor, where the type inference saves me a ton of time and pain.
The author does have a good point about the readability of code snippets, but the right approach is to render code with type annotations when outputting these formats, similar to syntax highlighting.
I do not miss having to change in32_t to int64_t at every location in my code when I changed my mind about types.
Seriously, that argument is like saying that long variable names are bad because sometimes you have to write code on punched cards. The solution to the drawbacks of obsolete technology is to not use obsolete technology.
While I read most of other people’s code in my IDE, the second most common spot is in code reviews. Hopefully that’s true for you as well, because I don’t really have time for the opinions of people who don’t participate in code reviews. They aren’t part of the conversation and can sod off.
So far, color highlighting is about the most I can expect from a CR tool. Though I’d be very open to being able to do CRS from my IDE.
> One of the author's arguments is that type inference in an IDE is bad because sometimes I read code in a book where I don't have type inference...
That feels like a bit of a straw man because you just took the weakest example from the author's list and took that single one out of context. The full quote was:
> But there are many other contexts where I read code: a book, a blog post, a Git diff. When editing code in a limited environment, e.g. stock vim in a VM.
In other words, there are other contexts that most programmers encounter in their day-to-day that don't have the benefit of autocomplete or popups. I think the general principle of "the code should stand alone" is a fair one to point out without just scoffing "Who reads code in a book??".
As a vim user, I have the same problems. I don't even have a mouse to hover over symbols either to see what their type is.
But even when I've used IDEs in the past, type inference still seems an unnecessary slowdown and pain in the ass to save 1 second of typing. Explicit types make the code a lot more readable, even if your IDE is capable of showing you the type.
> Type inference is bad. It makes code harder to read, and languages that use it too much are harder to write.
If inference is bad, maybe the second sentence shouldn't leave it up to the reader to infer what "it" means. Surely it would be much easier to read as "Type inference [...] type inference [...] type inference".
Funny enough this is the approach taken in legal writing as to limit misinterpretation... especially purposeful misinterpretation from opposition legal teams!
This results in highly repetitive, and as you've pointed out, somewhat tedious reading.
F# is my daily driver at work and I definitely benefit from both the type inference as well as my IDE making those types explicit for my reading pleasure!
- Omitting return types in non-private interfaces (eg crossing module or package boundaries, or anything used as input to generate documentation of same)
- Omitting concrete input parameter types
- Omitting explicit, known constraints on generic/polymorphic parameters
Subjective:
- Omitting any of the same on private equivalents which form something like an internal interface
- Omitting annotations of constant/static aspects of an interface whose inferred types are identical to their hypothetical annotation
Subjective but mostly good:
- Relying on inference in type derivation, where type derivation is the explicit goal of that API
- Preferring inference of interface/protocol/contract types over explicit annotation of concrete types which happen to satisfy them
- Omitting annotations for local bindings without distant indirection
Unambiguously good:
- Omitting local annotations of direct assignment where the type is obvious in situ
- Omitting redundant annotations of the same type which have the same effect without that redundancy
> In Rust and Haskell you have to at least annotate the parameter types and return type of functions. Type inference is only for variable bindings inside the function body.
I have run into situations where piping causes a type inference error but the equivalent function call doesn't, which is annoying because I have to use two different conventions in that case. I'm still an F# noob, so it's possible I'm doing something wrong.
I also get nervous that I'll change my function logic and the wrong type will be inferred, and it'll compile because the old and new types just happen to be logically compatible, but I get the wrong behaviour (or maybe this is just trauma from my VB6 days).
I tend to type my public function parameters and return parameters for this reason.
"My favorite languages feature types very prominently, therefore any software engineering approach that doesn't do so is invalid, and here are some reasons I thought of".
He posts this on HN, which happens to be built in Arc Scheme, a Lisp dialect (which is dynamically typed). I wonder if the author has written software that has better uptime and more popularity than HN? Is the author's codebase truly easier to understand?
Dynamically typed is a different scenario than statically typed with type inference. There are a whole lot more factors/considerations at play, and it's not helpful to confuse the two.
And what does it matter what HN is built on? Do you think any criticisms of C should not be posted on a site that runs on top of the linux kernel because the kernel is written in C?
What about when writing a function with polymorphic recursion, rank-N types, or the monomorphism restriction?
There are plenty of examples where a type declaration is required to get functionality, especially when we consider what GHC offers as being "Haskell".
I agree the author could be more clear about this—that Haskell and GHC only sometimes require type annotations in certain circumstances.
For me it makes sense to distinguish between type inference at the call site or the definition site. As a caller of a function, I don't want to have to spell out type parameters for that function if they can be inferred (but forcing inference is also not great because it's helpful to have type parameters that have nothing to do with the inputs and merely depend on the outputs).
At the definition site, I agree with the author that type inference is more of a burden for the most part, at least if the function is more than a hidden implementation detail of the class/module/file.
> For me it makes sense to distinguish between type inference at the call site or the definition site.
Bidirectional type checking kinda sorts this out by requiring annotations on top level functions and inferring or checking the rest in a mechanical manner. That's kind of a sweet spot or me. (And reportedly it's faster and gives better error messages.) Most dependent typed languages do this. I believe out of necessity. And Typescript also requires top level function definitions, but I haven't cheked if it is using the bidirectional algorithm.
If that's what the author is trying to say, then I agree. And with a Hindey-Milner system it's still best to annotate (most of) your top level functions (IMHO).
And I've gotten into trouble not doing this in the past. I started a project at work with flowjs, got inscrutable type errors in a different file than wherever the root cause was and bailed for typescript. In hindsight, it wasn't the fault of flowjs, but rather my lack of annotations on top level functions. (I knew far less about type-checking at the time.)
I think the article's take on type inference is a bit heavy-handed and misses some of the nuances of modern software development.
First off, the complaint about reduced readability outside of IDEs feels like a niche problem. Sure, it's a valid point when you're reading code on paper or in a basic text editor, but let's be real: most of us live in IDEs with excellent type hinting capabilities. The argument kind of falls apart when you consider that good variable naming can often make the need for explicit types less critical. Plus, isn't the goal of any good codebase to be as self-documenting as possible?
Regarding OCaml's type inference being a "footgun," it seems like a bit of an exaggeration. Yes, OCaml's system is powerful and can lead to some head-scratching moments, but isn't that just part of the learning curve with any powerful tool? It sounds like the frustration comes more from not leveraging the type system correctly rather than an inherent flaw with type inference. And honestly, adding type annotations for debugging is a pretty standard practice across many languages—not just OCaml.
The point about academic effort being wasted on type inference research also misses the mark. This research pushes the boundaries of what's possible with programming languages, leading to more expressive and safer languages. To frame this as a waste is to ignore the broader benefits of advancing programming language theory. Sure, it'd be nice if papers spent more time on practical applications, but that doesn't mean the theoretical aspects aren't valuable.
It feels like the article is conflating personal gripes with systemic issues. Type inference, when used correctly, can significantly reduce boilerplate and make code more concise and readable. Of course, it's not a silver bullet, and there are situations where explicit type annotations are beneficial for clarity, especially in public APIs. But to dismiss type inference outright seems like throwing the baby out with the bathwater.
In the end, it all boils down to using the right tool for the job and understanding the trade-offs. There's no one-size-fits-all answer in programming, and dismissing type inference entirely overlooks its benefits in many scenarios.
OCaml's type system allows for expressing complex data structures and behaviors in a concise and readable manner. These types can significantly improve code clarity by providing explicit declarations of intent and structure. Here are some examples:
type 'a binary_tree =
| Leaf
| Node of 'a binary_tree * 'a * 'a binary_tree
type http_response = [
| `Ok of string
| `Error of int
| `Redirect of string
]
module type QUEUE = sig
type 'a t
exception Empty
val empty: unit -> 'a t
val enqueue: 'a -> 'a t -> 'a t
val dequeue: 'a t -> 'a option * 'a t
end
type _ expr =
| Int : int -> int expr
| Bool : bool -> bool expr
| If : bool expr * 'a expr * 'a expr -> 'a expr
type person = {
name: string;
age: int;
address: string;
}
Bullocks. I wrote thousands if not hundred thousandths lines of untyped Python code in over 15 years, for critical systems and thousands of users.
It works for me. I'm not confused about the code, I can code and debug quicker than many of my typed-language colleagues and even now that python supports type hints I often only use them in bigger projects or in places where they're actually convenient.
It's simply the way of working that a developer is used to.
I inherited thousands of untyped Python code for critical systems, and it was an unmaintainable hot mess that caused a constant stream of pain. No kidding that was one of the main reasons we had to build a second version of the system.
I love Python, but I use it carefully in large scale production settings. Python with a Typescript-like static type system would hit the sweet spot for me (and yes, I've used mypy, but it doesn't hit the same spot).
Man I wish I could somehow convince developers to learn the difference between "dynamically typed", "statically typed", and "gradually typed" languages. An "untyped" language nearly doesn't make any sense semantically: when you have more than one type of value, you have types.
In Python's case, there are probably thousands of types in the standard library alone.
I think this article makes some really valid points. Many languages try to address the spooky action at a distance type errors by requiring explicit annotation of types at certain boundary type conditions like function argument and return arguments -- which can help but can still also being annoying when the type system knows the types you want to write but you still have to figure them out and type them in yourself. A lot of times it's less cognitive load to verify that a type declaration is what you expect than it is to write it yourself (something we often do with tools like rust-analyzer or highlighting over variables in ide to see the type).
Personally I'd like to see languages embrace "format on save" as an explicit part of language ui to improve ergonomics here. Firstly, a first class auto formatting tool is just great and spamming cmd-s as you write code until it auto formats nicely is a really quick way to observe and address syntax issues -- to me that part of the experience is already important enough to explicitly incorporate making that developer experience work well a goal of language design.
But secondly -- if you do embrace auto format on save at language design level, there's a lot more you can do than just auto format the code! You also gain a really nice channel for communicating information about "program change" to the developer. Say you allow in the language to differentiate between inferred and not inferred types -- and then at auto format time, the inferred types are explicitly added to the code (in some heuristically useful set of places-- or even just everywhere that a non type inferenced language would require explicit types).
In that world, as you make changes to the code, your git diff state is going to start giving you a lot of potentially useful feedback about what actually happens in your program when you make certain changes. Additionally because the inferred types are automatically added -- you can easily have a mode to hide them when you want a less noisy view. Mayb the convention would become that committeed code is always serialized to a form that conveys more of the statically knowable program information by default -- which your ide can hide to give you a more streamlined view -- rather than the other way around). And then the parts of your code you know are boundaries or apis or not expected to change types, you just update the annotation to indicate that the type is not supposed to be reinferred and a type error will be issued if it doesn't match instead of being updated. Now you've got a nice way of constraining program evolution in desired directions to help tame complexity or at least force explicit acknowledgement as certain assumptions about the program structure become invalid over time ...
In my experience IDEs and language servers for a language like F# have a convenient "Add explicit type annotation" that will do just as you're suggesting.
From what I can tell most functional programming tooling has this feature, but in the inverted manner from what you're describing for a language with explicit typing. You can hide the inferred type annotations but then have a key chord for showing them. I tend to just leave the annotations visible.
This is available for Rust. It might be for other languages. You can show the types as hints in the editor, or you can hover the variables to see the types. The latter is available for many languages, including Python and Go.
> languages that use it too much are harder to write. It’s a false economy whereby you save unobservable milliseconds of typing today and make everything else worse.
I enjoyed this reference to a false dichotomy while making one itself. Languages don't make programmers leave out annotations where it aids readability.
> Languages don't make programmers leave out annotations where it aids readability.
This is true, but most people are not going to incur write-time penalties to benefit read-time later on. Annotations (usually) benefit read-time at the expense of write-time. Having had to work on codebases that were written by people who were furiously trying to "get things done" because not shipping or shipping late might mean going out of business, they take whatever shortcuts they can. It ultimately saddles other people with tech debt for years and in some cases decades.
One of my dream ideas is to write a codemod that either adds all the implicit type inferencing explicitly, or removes it.
It's great that we don't have to type every type definition. But when reading code, it sure is much easier seeing exactly what every type is explicitly. You can look object by object in most ides by hovering over each item, but it doesn't have the at-a-glace see-it-all viewability; hence the idea, just rewrite the code with or without the explicit types, as desired.
There's still a lot of type narrowing and other things that happen that aren't super visible, that alter the known typing state as we go. I have less of an idea of what to do with that.
The claim about inferences rules in academic papers is false. Gentzen’s inference rules are usually used to specify how to type check and not type inference even though inference rules and type inference overlap in the use of the word inference.
Definitely disagree. The language where this really shines is Swift, where type inference is used really heavily.
It's really great for stuff like passing enums as function arguments. You can write `context.setColor(.red)` instead of `context.setColor(Color.red)`, the latter of which I find just unnecessarily repetitive.
The coolest part about this is when you're using a new unfamiliar API, you can let your IDE's auto complete suggest options for you just by typing '.' and pick from the list of options shown inline.
I get their argument on reading code in less than an IDE environment (ie. book), but in general, I think _limited_ type inference is good (on classes/structs and functions). Not having local variable types is a net positive in general, but I agree with the author that full type inference (on functions) removes too much documentation. In OCaml one should therefore use interface files always IMO.
The fact is that in many languages, type checking and type inference are coupled together (for languages with DT, bidirectional type checking is needed). When writing proofs, it is almost impossible to let user specify every type.
Ok, let’s go back to normal imperative programming. What about alias analysis? What to do with devirtualization? You NEED type inference.
That is being said, I am not a fan of the “usual” ocaml’s style where ppl seem to write as less type annotations as they can. That is not user friendly.
> I don’t want to infer types from my code. I’d rather infer the code from the types.
I use type inference for this: the compiler looks at the existing types and then infers the type of the code I haven't yet written and tells me. I then write code based on the type given to me by the compiler.
Hmm I code a lot in vim without any plugins (I just have syntax highlighting). It has never really been a problem for me (say in C++, Rust or Kotlin): I guess I'm training my memory a bit more?
I'll admit, once in a while I write something like `let a: Int = <the_var_which_type_I_dont_know>` and compile, such that the compiler says something like "expected an Int, got a HashMap<String, Int>". But pretty rarely.
In C# I've been preferring to only use var when the type appears in the expression so that it can be inferred by humans if you printed it out. In rust I've been using type inference per the usual rust coding conventions. I haven't quite sorted out in my head which way I really think is better.
> Type inference is only for variable bindings inside the function body. This is a lot more tractable.
Type inference inside a function body, is still type inference. Type inference gives us options and can sometimes improve readability. I find the title and premise of this article rather silly.
I agree with the idea that function return types should be explicit rather than inferred, but not the rest. In a lot of situations, inference makes it so you only have to spell the type once, instead of multiple times. That is valuable and doesn't reduce legibility.
Maybe write the types in the actual files and let the editors optimize it away instead of having it as a language feature. I don't want to see or write all the types in my daily work but when reviewing other peoples code I would like to have them.
But I can see the value of inference if the type is defined by a constant. If the rule is "Variables are the type of the constant that you assign in the definition, anything else is manual" it's pretty obvious.
Yeah no. OCamls is beautiful to write exactly because when you make a mistake, it will complain, and it's type inference works magic. You just have to learn the errors and think about what you changed when things broke.
I’ve been working with TypeScript and it’s literally wrong half the time. This code is 100% correct according to TS:
x: number[] = []
y: number = x[0]
The array type is missing information about the length of the array, and types are very often missing important information like this. Say you want to describe an array containing only odd integers - good luck.
Types are simply a heuristic for humans to try and remember vaguely what their code should do. If you want to do anything complex you need to abandon them anyway and use things like x!, and x as my_type. So designing around types seems like a bad idea.
You could do much better by abandoning text based programming languages and creating a visual programming language where you can zoom out and see what information gets passed where. The whole reason for types is to be a hack fix to the problem that we’re too zoomed in on their code and can only really reason about one function at a time given our crappy text-based programming languages.
This SOUNDS like “types are bad”. The author’s message (towards the end of the article) is “I don’t want to infer types from my code. I’d rather infer the code from the types. Types are the spec…”
Yes. Always annotate types. Keep inference, it tells you when your annotations are inconsistent with tour code.
nosefurhairdo|1 year ago
I don't know about other folks, but the vast majority of code I read is in my editor, where the type inference saves me a ton of time and pain.
lostdog|1 year ago
I do not miss having to change in32_t to int64_t at every location in my code when I changed my mind about types.
lisper|1 year ago
Seriously, that argument is like saying that long variable names are bad because sometimes you have to write code on punched cards. The solution to the drawbacks of obsolete technology is to not use obsolete technology.
hinkley|1 year ago
So far, color highlighting is about the most I can expect from a CR tool. Though I’d be very open to being able to do CRS from my IDE.
kqr|1 year ago
Adverblessly|1 year ago
hn_throwaway_99|1 year ago
That feels like a bit of a straw man because you just took the weakest example from the author's list and took that single one out of context. The full quote was:
> But there are many other contexts where I read code: a book, a blog post, a Git diff. When editing code in a limited environment, e.g. stock vim in a VM.
In other words, there are other contexts that most programmers encounter in their day-to-day that don't have the benefit of autocomplete or popups. I think the general principle of "the code should stand alone" is a fair one to point out without just scoffing "Who reads code in a book??".
freedomben|1 year ago
But even when I've used IDEs in the past, type inference still seems an unnecessary slowdown and pain in the ass to save 1 second of typing. Explicit types make the code a lot more readable, even if your IDE is capable of showing you the type.
ptx|1 year ago
If inference is bad, maybe the second sentence shouldn't leave it up to the reader to infer what "it" means. Surely it would be much easier to read as "Type inference [...] type inference [...] type inference".
williamcotton|1 year ago
This results in highly repetitive, and as you've pointed out, somewhat tedious reading.
F# is my daily driver at work and I definitely benefit from both the type inference as well as my IDE making those types explicit for my reading pleasure!
eyelidlessness|1 year ago
eyelidlessness|1 year ago
- Omitting return types in non-private interfaces (eg crossing module or package boundaries, or anything used as input to generate documentation of same)
- Omitting concrete input parameter types
- Omitting explicit, known constraints on generic/polymorphic parameters
Subjective:
- Omitting any of the same on private equivalents which form something like an internal interface
- Omitting annotations of constant/static aspects of an interface whose inferred types are identical to their hypothetical annotation
Subjective but mostly good:
- Relying on inference in type derivation, where type derivation is the explicit goal of that API
- Preferring inference of interface/protocol/contract types over explicit annotation of concrete types which happen to satisfy them
- Omitting annotations for local bindings without distant indirection
Unambiguously good:
- Omitting local annotations of direct assignment where the type is obvious in situ
- Omitting redundant annotations of the same type which have the same effect without that redundancy
muglug|1 year ago
phkahler|1 year ago
Like when I read about "auto" in C++. It still bugs me when I see it...
yazzku|1 year ago
> In Rust and Haskell you have to at least annotate the parameter types and return type of functions. Type inference is only for variable bindings inside the function body.
This is false for Haskell. Can't speak for Rust.
russellbeattie|1 year ago
CmdSheppard|1 year ago
aerhardt|1 year ago
Also, what do you build in F#? I think if I moved out of Python that would be it. OCaml is one of my favorite languages ever, and F# looks rad.
ryanjshaw|1 year ago
I also get nervous that I'll change my function logic and the wrong type will be inferred, and it'll compile because the old and new types just happen to be logically compatible, but I get the wrong behaviour (or maybe this is just trauma from my VB6 days).
I tend to type my public function parameters and return parameters for this reason.
ilaksh|1 year ago
He posts this on HN, which happens to be built in Arc Scheme, a Lisp dialect (which is dynamically typed). I wonder if the author has written software that has better uptime and more popularity than HN? Is the author's codebase truly easier to understand?
freedomben|1 year ago
And what does it matter what HN is built on? Do you think any criticisms of C should not be posted on a site that runs on top of the linux kernel because the kernel is written in C?
varjag|1 year ago
advisedwang|1 year ago
idle_zealot|1 year ago
blueboo|1 year ago
rqtwteye|1 year ago
swells34|1 year ago
unknown|1 year ago
[deleted]
PaulHoule|1 year ago
josephcsible|1 year ago
In Rust you do, but in Haskell you don't.
reikonomusha|1 year ago
There are plenty of examples where a type declaration is required to get functionality, especially when we consider what GHC offers as being "Haskell".
I agree the author could be more clear about this—that Haskell and GHC only sometimes require type annotations in certain circumstances.
Filligree|1 year ago
jupp0r|1 year ago
At the definition site, I agree with the author that type inference is more of a burden for the most part, at least if the function is more than a hidden implementation detail of the class/module/file.
dunham|1 year ago
Bidirectional type checking kinda sorts this out by requiring annotations on top level functions and inferring or checking the rest in a mechanical manner. That's kind of a sweet spot or me. (And reportedly it's faster and gives better error messages.) Most dependent typed languages do this. I believe out of necessity. And Typescript also requires top level function definitions, but I haven't cheked if it is using the bidirectional algorithm.
If that's what the author is trying to say, then I agree. And with a Hindey-Milner system it's still best to annotate (most of) your top level functions (IMHO).
And I've gotten into trouble not doing this in the past. I started a project at work with flowjs, got inscrutable type errors in a different file than wherever the root cause was and bailed for typescript. In hindsight, it wasn't the fault of flowjs, but rather my lack of annotations on top level functions. (I knew far less about type-checking at the time.)
greenavocado|1 year ago
First off, the complaint about reduced readability outside of IDEs feels like a niche problem. Sure, it's a valid point when you're reading code on paper or in a basic text editor, but let's be real: most of us live in IDEs with excellent type hinting capabilities. The argument kind of falls apart when you consider that good variable naming can often make the need for explicit types less critical. Plus, isn't the goal of any good codebase to be as self-documenting as possible?
Regarding OCaml's type inference being a "footgun," it seems like a bit of an exaggeration. Yes, OCaml's system is powerful and can lead to some head-scratching moments, but isn't that just part of the learning curve with any powerful tool? It sounds like the frustration comes more from not leveraging the type system correctly rather than an inherent flaw with type inference. And honestly, adding type annotations for debugging is a pretty standard practice across many languages—not just OCaml.
The point about academic effort being wasted on type inference research also misses the mark. This research pushes the boundaries of what's possible with programming languages, leading to more expressive and safer languages. To frame this as a waste is to ignore the broader benefits of advancing programming language theory. Sure, it'd be nice if papers spent more time on practical applications, but that doesn't mean the theoretical aspects aren't valuable.
It feels like the article is conflating personal gripes with systemic issues. Type inference, when used correctly, can significantly reduce boilerplate and make code more concise and readable. Of course, it's not a silver bullet, and there are situations where explicit type annotations are beneficial for clarity, especially in public APIs. But to dismiss type inference outright seems like throwing the baby out with the bathwater.
In the end, it all boils down to using the right tool for the job and understanding the trade-offs. There's no one-size-fits-all answer in programming, and dismissing type inference entirely overlooks its benefits in many scenarios.
greenavocado|1 year ago
thesuavefactor|1 year ago
angarg12|1 year ago
I love Python, but I use it carefully in large scale production settings. Python with a Typescript-like static type system would hit the sweet spot for me (and yes, I've used mypy, but it doesn't hit the same spot).
darby_eight|1 year ago
In Python's case, there are probably thousands of types in the standard library alone.
littlestymaar|1 year ago
Also you're confusing dynamic typing and type inference.
golergka|1 year ago
azhenley|1 year ago
mrkeen|1 year ago
Too hard. I need to see the types:
Is that even harder to read?> My response? Go refactor your hideous code.
breatheoften|1 year ago
Personally I'd like to see languages embrace "format on save" as an explicit part of language ui to improve ergonomics here. Firstly, a first class auto formatting tool is just great and spamming cmd-s as you write code until it auto formats nicely is a really quick way to observe and address syntax issues -- to me that part of the experience is already important enough to explicitly incorporate making that developer experience work well a goal of language design.
But secondly -- if you do embrace auto format on save at language design level, there's a lot more you can do than just auto format the code! You also gain a really nice channel for communicating information about "program change" to the developer. Say you allow in the language to differentiate between inferred and not inferred types -- and then at auto format time, the inferred types are explicitly added to the code (in some heuristically useful set of places-- or even just everywhere that a non type inferenced language would require explicit types).
In that world, as you make changes to the code, your git diff state is going to start giving you a lot of potentially useful feedback about what actually happens in your program when you make certain changes. Additionally because the inferred types are automatically added -- you can easily have a mode to hide them when you want a less noisy view. Mayb the convention would become that committeed code is always serialized to a form that conveys more of the statically knowable program information by default -- which your ide can hide to give you a more streamlined view -- rather than the other way around). And then the parts of your code you know are boundaries or apis or not expected to change types, you just update the annotation to indicate that the type is not supposed to be reinferred and a type error will be issued if it doesn't match instead of being updated. Now you've got a nice way of constraining program evolution in desired directions to help tame complexity or at least force explicit acknowledgement as certain assumptions about the program structure become invalid over time ...
cryptoxchange|1 year ago
williamcotton|1 year ago
whatever1|1 year ago
This way you can read the code more easily and if you want to see the type it's there for you.
williamcotton|1 year ago
maleldil|1 year ago
TulliusCicero|1 year ago
Now, if the IDE autocompletes the type declaration for me somehow, that's great! That's a win-win: I save time but still maintain readability.
schrodingerzhu|1 year ago
Then you will need type inference to some extend. :D
karmakaze|1 year ago
I enjoyed this reference to a false dichotomy while making one itself. Languages don't make programmers leave out annotations where it aids readability.
freedomben|1 year ago
This is true, but most people are not going to incur write-time penalties to benefit read-time later on. Annotations (usually) benefit read-time at the expense of write-time. Having had to work on codebases that were written by people who were furiously trying to "get things done" because not shipping or shipping late might mean going out of business, they take whatever shortcuts they can. It ultimately saddles other people with tech debt for years and in some cases decades.
jauntywundrkind|1 year ago
It's great that we don't have to type every type definition. But when reading code, it sure is much easier seeing exactly what every type is explicitly. You can look object by object in most ides by hovering over each item, but it doesn't have the at-a-glace see-it-all viewability; hence the idea, just rewrite the code with or without the explicit types, as desired.
There's still a lot of type narrowing and other things that happen that aren't super visible, that alter the known typing state as we go. I have less of an idea of what to do with that.
alanwang15|1 year ago
buzzert|1 year ago
It's really great for stuff like passing enums as function arguments. You can write `context.setColor(.red)` instead of `context.setColor(Color.red)`, the latter of which I find just unnecessarily repetitive.
The coolest part about this is when you're using a new unfamiliar API, you can let your IDE's auto complete suggest options for you just by typing '.' and pick from the list of options shown inline.
nu11ptr|1 year ago
germandiago|1 year ago
schrodingerzhu|1 year ago
Ok, let’s go back to normal imperative programming. What about alias analysis? What to do with devirtualization? You NEED type inference. That is being said, I am not a fan of the “usual” ocaml’s style where ppl seem to write as less type annotations as they can. That is not user friendly.
joshspankit|1 year ago
Ditto.
The world where data and it’s type is the SSOT means you can trivially validate every bit of code that touches it.
mrkeen|1 year ago
I use type inference for this: the compiler looks at the existing types and then infers the type of the code I haven't yet written and tells me. I then write code based on the type given to me by the compiler.
palata|1 year ago
I'll admit, once in a while I write something like `let a: Int = <the_var_which_type_I_dont_know>` and compile, such that the compiler says something like "expected an Int, got a HashMap<String, Int>". But pretty rarely.
So yeah, I kind of like type inference.
lamontcg|1 year ago
grumpyprole|1 year ago
Type inference inside a function body, is still type inference. Type inference gives us options and can sometimes improve readability. I find the title and premise of this article rather silly.
loeg|1 year ago
klipt|1 year ago
One could argue it's better for type inference to not just be part of the language but also part of the IDE. E.g. you type
auto x = ...
And then the IDE offers to replace the auto with vector<SomeClass>
That way you can both write code with type inference, but read code with fully annotated types!
Adverblessly|1 year ago
AtNightWeCode|1 year ago
eternityforest|1 year ago
But I can see the value of inference if the type is defined by a constant. If the rule is "Variables are the type of the constant that you assign in the definition, anything else is manual" it's pretty obvious.
thefaux|1 year ago
jenny91|1 year ago
esafak|1 year ago
apples_oranges|1 year ago
danielmarkbruce|1 year ago
nurettin|1 year ago
All this visual help makes a lot of pet arguments obsolete.
andrewp123|1 year ago
x: number[] = []
y: number = x[0]
The array type is missing information about the length of the array, and types are very often missing important information like this. Say you want to describe an array containing only odd integers - good luck.
Types are simply a heuristic for humans to try and remember vaguely what their code should do. If you want to do anything complex you need to abandon them anyway and use things like x!, and x as my_type. So designing around types seems like a bad idea.
You could do much better by abandoning text based programming languages and creating a visual programming language where you can zoom out and see what information gets passed where. The whole reason for types is to be a hack fix to the problem that we’re too zoomed in on their code and can only really reason about one function at a time given our crappy text-based programming languages.
thomasrognon|1 year ago
unknown|1 year ago
[deleted]
z5h|1 year ago
Yes. Always annotate types. Keep inference, it tells you when your annotations are inconsistent with tour code.
kqr|1 year ago
Isn't that plain type checking, rather than type inference?
Type checking detects inconsistencies, type inference assigns types in ways that avoid inconsistencies.
mrkeen|1 year ago
No, this sounds like:
* Type Inference Was a Mistake
* Type Inference Makes Code Less Readable
* Type Inference is a Footgun
* Type Inference Wastes Academic Effort
These are incompatible with:
> Keep inference