3 ms·
Regarding the lack of examples, the type system is strong enough that in many cases, if you write the types that you expect up front, there's only one or few po
by Silhouette 6y ago
Regarding the lack of examples, the type system is strong enough that in many cases, if you write the types that you expect up front, there's only one or few possible implementations.
This is a common counter-argument. It is a true statement. And, in the nicest possible way, it is also completely missing the point.
When you're playing with cute mathematical code and almost everything is written in terms of totally generic types, it's cute that you get free theorems and automatic derivations of some basic functions and all that stuff.
However, in the real world, 99% of the time we work with concrete types to get concrete work done, and there are going to be many possible implementations of a function of type Int -> Int, or MyDataStructure -> MyDataStructure -> MyDataStructure, or SomeWrapper SomeType -> (SomeType -> SomeOtherType) -> (SomeType -> SomeOtherType) -> SomeWrapper SomeOtherType. This remains true notwithstanding the possibility that some of that cute generic code was used to implement various small parts of the function you actually care about if you dig down far enough.
This means the type signatures aren't simply documentation, they also strongly direct your implementation. The problem from a marketing and adoption standpoint is that this isn't visible until you've hopped into a REPL or IDE and tried it yourself.
I would argue that the problem from a marketing and adoption standpoint is that it still isn't visible even if you do do those things, unless you're interested in writing heavily mathematical generic code rather than completing the job your boss told you to do within a reasonable timeframe.
- dragonwriter 6y ago> However, in the real world, 99% of the time we work with concrete types to get concrete work done, and there are going to be many possible implementations of a function of type Int -> Int, or MyDataStructure -> MyDataStructure -> MyDataStructure, or SomeWrapper SomeType -> (SomeType -> SomeOtherType) -> (SomeType -> SomeOtherType) -> SomeWrapper SomeOtherType. But, on the gripping hand, using types unspecific enough that that is the case is often a sign of underusing the type system. E.g., very few domains actually deal with bare numbers as domain values, and when you express concrete types specific enough, there may be more than one possible correct function, Bru very often the one actually correct function will be much more obvious, and the mistakes possible by omitting a step when using less-robust sets of types become impossible because you effectively have statically verified dimensional analysis.
- Silhouette 6y agoAs a general rule, I am all for defining specific aliases of fundamental types, type-safely if possible. I don't think this changes my argument materially, though. Real world applications of programming always come down to processing data of known, concrete types at some point. And at that point, all the power you get from saying things like there's only one possible implementation of a function f :: a -> a immediately go out of the window, because you don't have a value of type a, you have a value of type SomeConcreteTypeThatIKnowThingsAbout. In my experience, though of course yours may differ, there are very often still many plausibly correct implementations of functions working with those types and many ways to combine them that might make sense and that would satisfy the type checker. The idea that specifying the types alone is a viable substitute for proper documentation of the real meaning of the functions just falls apart at that point.
- codygman 6y ago> And at that point, all the power you get from saying things like there's only one possible implementation of a function f :: a -> a immediately go out of the window, because you don't have a value of type a, you have a value of type SomeConcreteTypeThatIKnowThingsAbout. Not if your logic is primarily in terms of domain types, invariants encoded in those domain types as is necessary and economical. > And at that point, all the power you get from saying things like there's only one possible implementation of a function f :: a -> a immediately go out of the window, because you don't have a value of type a, you have a value of type SomeConcreteTypeThatIKnowThingsAbout. Can you give an example? I can only see this being the case if your logic is done at the concrete type level.
- Silhouette 6y agoI wonder if we're talking at cross-purposes here. While it is certainly useful to write abstractions of common algorithms and access patterns for data structures generically, any useful program ultimately has to deal with data of known types. Those might come from the domain model, or they might be implementation tools like file handles or database queries, but they are something specific, some concrete type that is relevant to the problem at hand.
- codygman 6y ago> This is a common counter-argument. It is a true statement. And, in the nicest possible way, it is also completely missing the point. Yes, kind of. > When you're playing with cute mathematical code and almost everything is written in terms of totally generic types, it's cute that you get free theorems and automatic derivations of some basic functions and all that stuff. It's not only "cute" as you so reductively put it. There are real world benefits. > However, in the real world, 99% of the time we work with concrete types to get concrete work done, and there are going to be many possible implementations of a function of type Int -> Int, or MyDataStructure -> MyDataStructure -> MyDataStructure, or SomeWrapper SomeType -> (SomeType -> SomeOtherType) -> (SomeType -> SomeOtherType) -> SomeWrapper SomeOtherType. This remains true notwithstanding the possibility that some of that cute generic code was used to implement various small parts of the function you actually care about if you dig down far enough. That presumes an arguably wrong method of developing software that needlessly eschews understanding and correctness confused for superior economic choices, finally resulting in "real world programming".