5 ms·
Time to market? Type inference solves a different problem - it doesn’t help you here. For example type Money { amount: Amount, currency: C
by CraigJPerry 6y ago
Time to market?
Type inference solves a different problem - it doesn’t help you here. For example
type Money {
amount: Amount,
currency: Currency
}
Money(USD, 10) + Money(EUR, 10) # what type should be inferred here?
A runtime exception maybe?
(There’s no “best” answer here, a runtime exception might be the pragmatic choice but i like the Map<Currency, Amount> solution to this).
- skohan 6y agoUnless your application is implemented in under 100 lines, types will save you time in general
- CraigJPerry 6y agoThis is obviously false, it’s just too general a statement. Type errors are such a small time loss as a developer - when i think of the things that lose me time, it’s things like domain complexity, misunderstood requirements, not “ooops i passed a string instead of list of string”. I wondered if there are any studies that support your assertion? The first few results in Google all refute your idea though, e.g. https://www.researchgate.net/publication/259634489_An_empirical_study_on_the_impact_of_static_typing_on_software_maintainability https://www.researchgate.net/publication/259634489_An_empiri... Or https://www.ics.uci.edu/~jajones/INF102-S18/readings/23_hanenberg.pdf https://www.ics.uci.edu/~jajones/INF102-S18/readings/23_hane... And that intuitively makes sense. When i’m adopting types, time saving isn’t really what i’m buying. It’s the opposite - i’m saying “hey, i want to invest more time into this to help ensure correctness” - i.e. i am happy to wrestle with the type system if it means the delegation frees my brain for solving the problem. And this comes back to what i mentioned earlier about domain complexity - you can use types to help make that easier to manage, often though, it’s better to push harder to eliminate complexity in the first place. Occasionally that’s just not possible, it’s a complex problem domain not another CRUD webapp, in those cases types are fantastic.
- skohan 6y ago> Type errors are such a small time loss as a developer It's not about the errors themselves, it's about the way that having a strong type system improves quality of life in general. For instance, in a duck-typed language, you may have code which runs correctly 99/100 times, but with one specific case it fails due to type issues. These kinds of issues are incredibly frustrating and time-consuming to debug. Also requiring type designations in function signatures makes code self-documenting. You can just look at the code which someone else wrote, and know exactly what the inputs and outputs are. In a dynamically typed setting, there's often guess work involved in exactly what's accepted by a function, and unless it's very well documented you might have to go into the implementation to see exactly what is happening. I didn't read the articles you linked in detail, but at least the first I would take with a grain of salt since they use Java as the exemplar for typed programming. Java is notorious for having a cumbersome type system. In my experience, without types you might get a slightly faster time to first result - but in the long term, once a codebase gets to even medium size, types save you much more time than they cost. Especially since they become automatic after a bit of experience and you don't even think about it anymore. There's a reason Python and Javascript are trying to add types, and why none of the most interesting languages of the past decade have been weekly typed.
- CraigJPerry 6y agoI think you might have missed my point, it’s not a binary good/bad - both approaches have a useful place.
- skohan 6y agoI think we just disagree. I understand your point, but I think that the benefits of having strong types outweigh any drawbacks in almost all cases. The benefits are huge once you get past a very small program (100 lines was a little flippant on my part) and the drawbacks rapidly approach zero for any sufficiently well-designed type-system
- CraigJPerry 6y ago
- exdsq 6y agoIt would help catch the fact you wrote it as both <Currency, Amount> and <Amount, Currency>
- CraigJPerry 6y ago:-) >>> class Money: ... def __init__(self, currency, amount): ... self.m = Counter({currency: amount}) ... def __add__(self, other): ... self.m += other.m ... >>> Money("USD", 10) + Money(10, "EUR”) Traceback (most recent call last): File "<string>", line 1, in <module> File "<string>", line 5, in __add__ File "/var/containers/Bundle/Application/F8EBA093-47B6-4538-A3A5-553C9C2234FA/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/collections/__init__.py", line 805, in __iadd__ self[elem] += count TypeError: unsupported operand type(s) for +=: 'int' and 'str' Even Python yells at me for that. In all seriousness though, how far do such mistakes survive? Not past compile here, but in other cases it could. Could it pass tests? Unlikely. Could it pass casually running the code, not impossible but again seems unlikely. How many PRs on Github for projects written in dynamically typed languages are things that would be caught by static types? Some, it’s non-zero, it’s not anywhere close to a significant proportion though.
- joshuamorton 6y agoFwiw there are type systems that can catch this. C++, rust, and pythons in fact both have support for erroring on this by default, unless you have overridden the addition operator for Money to always result in the lhs or the currency, or whatever. See, for example, the absl::Duration apis in c++.
- CraigJPerry 6y agouse std::ops::Add; fn main() { let usd = Money { currency: String::from("USD"), amount: 10 }; let eur = Money { currency: String::from("EUR"), amount: 10 }; dbg!(usd + eur); } #[derive(Debug)] struct Money { currency: Currency, amount: Amount } impl Add for Money { type Output = Money; fn add(self, other: Money) -> Money { Money { currency: self.currency, amount: self.amount + other.amount } } } type Currency = String; type Amount = i32; // i know :-) This outputs 20 USD in rust, it’s a design problem not a types problem.
- joshuamorton 6y agoI'm not sure what your point is. It's glaringly obvious that this code is functionally wrong, in no small part bc of the type information.
- CraigJPerry 6y agoAhh no, the code isn’t functionally wrong, take for example: Money(“USD”, 10) + Money(“USD”, 5) This works just fine. We’d need more context about how it’s used to say whether we’ve made a bad trade off with our design. The error isn’t represented in the types, that’s why it compiles and runs. The compiler can’t see the design error here, which is fair, it’s a design problem and types don’t fix that - people are free to misunderstand the business domain and happily capture the wrong rules in types.
- danielscrubs 6y agoYou have declared the domain the function handle and then you don’t handle it, simple as that.