Are there any known principles, best-practices and design patterns that one can follow while writing code in a functional programming language?
Design pattern: let the compiler infer types for your functions, and make sure those types are exactly as general as you expect. If the types are more polymorphic or less polymorphic, figure out why.
For example, if you are writing a sort function in Haskell, expect
Ord a => [a] -> [a]
If your type is
Num a => [a] -> [a]
or
[a] -> b
then something is horribly wrong.
Best practice: once you've confirmed with the compiler that the type is as you expect, put an explicit type signature for every top-level function. (Or if you are using ML or Caml, write an explicit interface.) Set compiler options so that values with missing signatures trigger an error.