Are there any known principles, best-practices and design patterns that one can follow while writing code in a functional programming language?
Best practice: use algebraic data types and take advantage of exhaustiveness checking from the pattern-match compiler. In particular,
Never match a wildcard pattern _ at top level.
_
Set compiler options so that a missing case in a pattern match is an error, not a warning.