| This question actually has a simple answer: Most languages have embraced statements over expressions for a lot of language constructs. This causes a lot of issues: An if-statement is in essence a function from boolean to unit/() (i.e. from a barely useful type to a type with no useful information), while an if-expressions will contain enough type information to at least provide this kind of “flow typing”, (even if it induces an amount of boolean blindness.) It’s even worse when you get to loop-statements, which often is a function from unit/() to (unit/() | bottom/⊥), compared to a map or a reduce or fold, which again provide enough type information to provide this kind of “flow typing”. Sometimes you will of course need to provide impure conditionals or loops, but that can be made explicit in the type system. IMHO statements in programming languages are an anti-pattern. |
Expression-based languages tend to have pattern matching which provides another way to solve the same problem.
Flow typing is most useful in imperative languages where code like this is common:
Early returns and other imperative control flow is idiomatic and it's annoying if the static type system doesn't understand it.In a more functional or expression-oriented language, early returns and other imperative control flow like that is rarer, so there's less "flowing" to type over.