Re:Things I Was Wrong About: Types
by lgas on Sunday September 27, 2020 @12:20PM
(#24607780)
I moved (very roughly) from Java to Python to Haskell. When I was coding in Python if you asked me what percentage of bugs I encountered could have been caught by types, I would've probably said about 10%. Because I would've been thinking about types in Java and errors like calling "length" or a string and then accidentally calling "length" again on that int value from the previous call to length.
Now that I am working primarily in Haskell if you ask me the same question I would say probably about 90%. Not only does catching the "calling length on an int" types of errors at compile time but it gives you whole new tools (newtypes, Sum types, mtl-style constraints) for expressing complex concepts in a simple manner in the type system.
And all of these tools result in having to spend much less time thinking about things I had to think about in python, leaving me to spend more time thinking about the business logic which reduces the number of logical errors (which obviously can still occur).
You can see on line 57 "unless (status == Fresh) $ do" -- I originally wrote checkStatus as a function that returned a boolean and the expression was "unless fresh $ do" but I replaced the boolean with a tri-valued sum type and rewrote the check against the value "Fresh" -- this avoids the boolean blindness problem and makes it much harder to get the condition wrong -- and while it's still possible to get the condition wrong, it's much easier to find it when you do.
Now that I am working primarily in Haskell if you ask me the same question I would say probably about 90%. Not only does catching the "calling length on an int" types of errors at compile time but it gives you whole new tools (newtypes, Sum types, mtl-style constraints) for expressing complex concepts in a simple manner in the type system.
And all of these tools result in having to spend much less time thinking about things I had to think about in python, leaving me to spend more time thinking about the business logic which reduces the number of logical errors (which obviously can still occur).
As a concrete example I transliterated some Python code that someone was asking about on reddit into Haskell here: https://gist.github.com/lgastako/f7465339214c6fde0fd75f4e488...
You can see on line 57 "unless (status == Fresh) $ do" -- I originally wrote checkStatus as a function that returned a boolean and the expression was "unless fresh $ do" but I replaced the boolean with a tri-valued sum type and rewrote the check against the value "Fresh" -- this avoids the boolean blindness problem and makes it much harder to get the condition wrong -- and while it's still possible to get the condition wrong, it's much easier to find it when you do.