Haskell is primarily a pure functional language. Functional meaning emphasizing function manipulation, building monumental programs by composing many small functions. But unlike Lisp, Haskell is "pure", meaning rigidly policing side effects, not only favoring map over loop, but separating in the type system random number generators and socket I/O from Fibonacci and regex's, because while fib and sub operate in MathLand, side effects require special considerations; when you're processing a bank transaction, who withdraws what and deposits how much in where in what order—
All of that is relevant. It's like you're implementing semaphores all the time.
But that code purity allows Haskell to alter control flow in practical ways, engaging a multitude of programming paradigms. Monads are specialized tools for operating on pure code, enabling one word optimizations: to parallelize code that maps over a list, just change that call to parmap. To memoize fib, say memo fib; or use the Acc data type for behind-the-scenes GPU coding; quickCheck for unit testing arbitrarily complex systems... Haskell can do these things by controlling program flow with monads. Monads have been described by Simon Peyton Jones as ensuring that when the user presses the Fire Missile button and a hook triggers a comprehensive test framework that tests missile circuitry a thousand times in a microsecond, the program still executes "Fire missile!" exactly once. Where Haskell departs from Scheme and Ruby, because they're hip, they have map, they have reverse and reverse!, is it takes those exclamation marks and runs with them, unlocking a new universe of computational ability.