6 ms·
Pattern matching for one. I can prove that 3 cases won’t be met but I have to ‘fill in’ them anyway. ADTs with non-Maybe fields. I can prove that all is fine i
by wellpast 7y ago
Pattern matching for one. I can prove that 3 cases won’t be met but I have to ‘fill in’ them anyway.
ADTs with non-Maybe fields. I can prove that all is fine if this ‘slot’ isn’t filled in.
Trying to pass an opaque reference down a function call chain.
There’s 3.
- wellpast 7y agoAnd these are insanely expensive to deal with over time when you compare to the alternative.
- mbrodersen 7y ago> insanely expensive Wow that sounds really expensive! How did you actually measure that in the real world?
- wellpast 7y agoI spent too many years programming in all kinds of dynamically typed and statically typed systems and I kept a clear head and didn't cling to a blind religious persuasion. I've also watched the performance of static type enthusiasts closely. I thought that when I updated a type that all of my running around fixing type errors had to do with me missing something but alas that was not the case. This is how the static enthusiasts do their work, all the while claiming that they are being more productive. When I call a static typer our on this the answer is always the same: "But you'd have to go update those case statements/maybe matches/type signatures anyway!" Meanwhile I'm over in a dynamic system not having to do any of that. Refactors are minimal not cross-the-entire-codebase. Static type systems are training wheels. When a static type enthusiast takes his training wheels off, the bike falls over and s/he screams "See! I told you. I'm more productive with types!" And then they put the training wheels back on and think that they have proven that static verification is superior. What they don't know is that there is enormous missed opportunity once you learn how to ride a bike w/o training wheels. The truth is you can produce much faster without a rules-based static type prover between you and your runtime environment if you know what you're doing. This should be obvious b/c in one world you have a filter/prover that you must past to ship. In the other world you do not. If the filter/prover was worth its weight then you should be able to clearly see the win. But in business systems the kinds of bugs found by filter/provers are of the "null pointer" variety -- the fastest and simplest bugs to fix when they are found; having a heavyweight filter/prover save me from these simplest of bugs to fix is simply not worth it.
- mbrodersen 7y agoLook I have been programming for 35+ years in both dynamic and typed languages. And my experience is that I am more productive when using a typed language. It sounds as if your experience is the opposite. I wonder why our experiences are so different? It would be interesting to find out.
- tome 7y agoIf you have a place where you emit sum types, and you increase the set of possible cases you can emit then you do have to cross-the-entire-codebase to update all consumers of that sum type to handle the new case. If you have a place where you consume product types, and you increase the set of fields that you inspect on that sum type, then you do have to cross-the-entire-codebase to update all producers of that product type to emit the new field. I don't see how it could be any different. How would you handle this in Clojure?
- wellpast 7y agoHere’s another that kills me every time, I want to compose where I know types are mismatched and I am okay with a runtime fault downstrean. This is hugely powerful to move very fast in, eg, REPL-driven development environment where you build and verify pieces of code incrementally. Not being able to do this is a enormous productivity killer, relative to say a dynamic/Clojure.
- tome 7y ago> I want to compose where I know types are mismatched and I am okay with a runtime fault downstrean. Sounds like another good candidate for `error` or `undefined`
- mbrodersen 7y agoRight. And when another programmer changes the ADT so that this is no longer true your dynamic language will now crash in production instead of telling you right away before putting it into production? Or are you telling me that your code always have 100% code test coverage checking all possible execution paths for all pattern matches?
- tome 7y agoSure, thanks, I know where Haskell's type system will ask you to try again if you haven't provided all the information it wants. I'm asking for examples where it genuinely wasn't sensible to change your code to match what the compiler wants. > Pattern matching for one. I can prove that 3 cases won’t be met but I have to ‘fill in’ them anyway. This is a funny one because, no, GHC will not ask you to fill them in! You have to turn on a warning for it to complain. The fact that the warning is not on by default is one of my pet peeves with GHC! > ADTs with non-Maybe fields. I can prove that all is fine if this ‘slot’ isn’t filled in. Another funny one, because you can just use `undefined` or `error` and GHC won't complain! Personally I'd probably prefer that it did. > Trying to pass an opaque reference down a function call chain. I don't even know what you mean by that.
- wellpast 7y ago> Pattern matching for one. I can prove that 3 cases won’t be met but I have to ‘fill in’ them anyway. >> This is a funny one because, no, GHC will not ask you to fill them in! You have to turn on a warning for it to complain. The fact that the warning is not on by default is one of my pet peeves with GHC! Okay, so let's do the inverse then. I've got a pattern matched case that the type prover proves will never occur (so it throws type error) but I want it to occur. The answer I know is obvious: I have to add it to the type union. But it should be obvious at this point that the moves I am making are not driven by the outcome I want but by the rules of the type checker. At some point you have to say, Why am I playing these games? Do they really yield tangible, business-facing value? > ADTs with non-Maybe fields. I can prove that all is fine if this ‘slot’ isn’t filled in. >>Another funny one, because you can just use `undefined` or `error` and GHC won't complain! Personally I'd probably prefer that it did. But I don't want an error. I can prove that the absence of the field is OK/not-an-error. If you say then make it a Maybe, I will tell you sorry I don't have the time to update my entire code-base to contend w/ this novelty to the type checker (I say to the type checker, but this is never a novelty to me and my dynamic code). > Trying to pass an opaque reference down a function call chain. >> I don't even know what you mean by that. my value --(flows at runtime through)--> [some framework, say a web framework code to a, say, a Label that has no idea about my value's type domain] --(flows through pixels to)--> user's eyes