8 ms·
> The problem with complicated and/or specific types (which promise to catch more errors) is, in one word, coupling. They create serious dependencies across the
by adwn 10y ago
> The problem with complicated and/or specific types (which promise to catch more errors) is, in one word, coupling. They create serious dependencies across the whole project or even across project boundaries.
With dynamic typing, you'll still have this coupling, but now it's unchecked and (in practice) undocumented.
- jstimpfle 10y agoMost parts of the code don't actually care about all aspects of the type (or the value), but only that it's an object that they can hand to the next function. Or they only care about a subset of the value's properties (like it being a string, not necessarily a URL). For example, in Haskell there is the filter function: filter :: (a -> Bool) -> [a] -> [a] filter _ [] = [] filter pred (x:xs) | pred x = x : filter pred xs | otherwise = filter pred xs It doesn't actually care what (the type of) a is. This is one of the showcase examples of the power of Haskell's typesystem. (And admittedly it works nicely in this case). But you can have that easily with no typing at all. def filter(pred, xs): return [x for x in xs if pred(x)] So, dependencies avoided and it's not a huge source of bugs. While in the typed case, a system is needed to prove that the properties that get input come out again (or possibly a function of these properties). That quickly gets quite involved for more advanced cases. Just look what the average Haskell code looks like, how many language extensions are typically needed, how crippled the code typically is (libraries dictating exactly what properties the client must be able to statically precompute). Most of the Haskell community seems to agree that the end-goal would be a practical system for dependent types (the unification of types and values, i.e. no types at all ;->). For example, there are some libraries trying to capture the construction and execution of valid SQL queries in the type system. To understand these libraries without doubt a genius-level IQ is required. But the client code is still basically an unreadable mess. And the libraries are not reusable for cases where the database schema isn't known at compile time. The static type system actually prevents code reuse -- it makes the code really inflexible.
- watwut 10y agoThese super general very reusable functions are just a small part of code. Most of it depends on how arguments objects looks like exactly. It all becomes much harder to maintain the moment the project grows bigger or you are new to it. Types make it much easier to figure out what is allowed as a parameter where and what I am expected to do in order to make the system work. When I switched from typed to untyped language, it was like having hands cut off.
- jstimpfle 10y agoYou are making my point, I'm very much in favor of primitive or very simple types. More complex types typically have a bad cost to benefit ratio. And it's quite doable to get by even without these simple-type annotations. Just put some assertions at strategic locations. Of course there still is some amount of debugging involved. On the other hand development was much cheaper at other places, and once it works you can be reasonably confident that an int will not turn into a string overnight.
- vosper 10y agoThe problem with assertions is that sometimes they mean people get woken up in the middle of the night for an issue that would have been caught hours/days/weeks before by a statically-typed language. If you don't have 100% test coverage in Python you just can't rule that possibilility out. I say this as a full-time Python engineer and I've been woken up at 3am by things that slipped through testing and would have been caught in (say) Java or C#. Now, it is arguable whether it's worthwhile to take that chance to make development quicker and more flexible. I can definitely see that. Also, if you have to wait a long time for the compiler then that might actually be a loss in aggregate. It does suck trying to refactor large Python codebases though. Running and fixing the tests over and over until errors go down to zero is no fun.
- crdoconnor 10y ago>The problem with assertions is that sometimes they mean people get woken up in the middle of the night for an issue that would have been caught hours/days/weeks before by a statically-typed language. If you don't have 100% test coverage in Python you just can't rule that possibilility out. I say this as a full-time Python engineer and I've been woken up at 3am by things that slipped through testing and would have been caught in (say) Java or C#. For me, carefully placed assertions combined with a comprehensive (but not 100%), test suite nearly always means A) catching the exception with a test or B) a clear production error that indicates a problem with the production environment. I've been woken up plenty by poorly written Java that has had its type system intentionally weakened by terrible coders, meaning lots of detective work. It's a fallacy is that dynamic automatically means weak and static automatically means strict. Assertions aren't just useful in dynamically typed languages. Java would benefit from using them as well.
- adwn 10y agoThat's actually a great argument for static typing! Let's say your distant input component is changed and in some cases doesn't send lists of lists, but one flattened list. With Haskell, the compiler will immediately notify you of this bug, while with Python, you have to hope that your integration tests are sufficiently exhaustive to catch this, or you'll catch it in production. Whoops. Like I said, the coupling is still there, but it's hidden by dynamic typing.
- jstimpfle 10y agoIn most cases you will not be able to write your code in Haskell in the first place. Do try to write a database query construction kit that deals with schemata read at runtime (a very reasonable requirement). Even for a non-genius it's pretty easy to make something that works, with dynamic types. http://jstimpfle.de/projects/python-wsl/main.html http://jstimpfle.de/projects/python-wsl/main.html I don't think something like that can be created in Haskell (without resorting to dynamic types).
- Filligree 10y agoYou always have dynamic typing as an escape. If that's what it takes, then that's an option, but I think in practice you'd be able to keep that sort of purity to a small portion of the program. Haskell is a research language, which sometimes shows in the libraries. I'm not sure if I'd recommend it for general use; I'm more partial to Kotlin these days. It's definitely an interesting approach, though, and anyone who's designing languages ought to make themselves familiar.
- Filligree 10y agoYou always have dynamic typing as an escape. If that's what it takes, then that's an option, but I think in practice you'd be able to keep that sort of purity to a small portion of the program. Haskell is a research language, which sometimes shows in the libraries. I'm not sure if I'd recommend it for general use; I'm more partial to Kotlin these days. It's definitely an interesting approach, though, and anyone who's designing languages ought to make themselves familiar.
- 10y ago
- renesd 10y agoIn python, you could type it fairly loosely. Which is more readable, and also helps you catch errors. There's not so much coupling. from typing import Callable, Iterable def filter(pred: Callable, xs: Iterable) -> Iterable: return [x for x in xs if pred(x)] filter(lambda x: x>1, [1,2,3]) If you tighten it up to only take iterables of ints. from typing import Callable, Iterable def filter(pred: Callable, xs: Iterable[int]) -> Iterable: return [x for x in xs if pred(x)] filter(lambda x: x>1, [1,2,3]) filter(lambda x: x>1, [[1],[2],[3]]) # this is an error Float is duck type compatible with int. So if you specify float, it accepts ints and floats. If you specify int, it only accepts ints. from typing import Callable, Iterable def filter(pred: Callable, xs: Iterable[float]) -> Iterable: return [x for x in xs if pred(x)] filter(lambda x: x>1, [1,2,3]) filter(lambda x: x>1, [1.01, 2.09, 3.34]) The moral of the story is to be as accepting as you can be unless there is an actual need to be very picky about what you accept. (Perhaps if you're doing integer arithmetic, and your code only works with ints, then require ints).
- lngnmn 10y agoThe very beauty and reason behind filter is in that it does not care about its arguments. It is a logical construct - if predicate is satisfied - keep it. The ADTs, type-tagging, predicate logic and duck-typing are superior and less cluttered than homogeneous box-like variables and restricted homogeneous conditionals are - the cost of static typing. Yes, one could shot himself in the foot, but one also could run instead of crawl.
- renesd 10y agoQuack, quack. I'm a duck.
- mannykannot 10y agoSometimes it is more important to not shoot oneself in the foot than it is to run. These discussions always end up with two antagonistic camps, so let's acknowledge that we can choose the degree of language support, in keeping a program's semantics as intended, according to the circumstances. Language selection is an aspect of engineering judgement.