Algebraic data types and pattern matching actually work really well in imperative languages, too. See eg Rust.