The other restrictions brought by languages like Haskell catch classes of error you do see in Python.<p>For example, with django&#x27;s forms, you are forced to call validation (`form.is_valid()`) before you can get the result of said validation (`form.cleaned_data`)<p>So referencing `form.cleaned_data` before  `form.is_valid()` is incorrect....<p>If you had to port something like Django&#x27;s forms to Haskell, you could instantly get rid of this issue because such behaviour <i>is impossible to express</i> in the language.<p>In Haskell you would likely write a `validate` function that takes a form, and returns either a validation error or the validated data itself: `let maybeCleanedData = validate form`<p>The type system that makes effects explicit (really, the immutable nature of everything, but one and the other usually synergise well) means that your API is forced to be a saner one.<p>You can take what you learn from these type systems and bring it back to Python though. Like you said, most errors are logic errors. But logic errors can often be helped along by dangerous APIs. Types and removal of stateful code can give you the boundaries to rule out many designs that can come back to bite you.