Haskell is a hard language because (a) laziness is not intuitive, especially when space-performance matters (sadly, it does) and (b) pure functional programming is just not practical for most people. Like the OP said, it's awesome for brain-stretching, but not the easiest language to use. I started writing a game in Haskell and found that the scaffolding necessary to do randomness in the "right" way was just too pain…
http://hackage.haskell.org/packages/archive/random/1.0.0.2/d...
getStdRandom :: (StdGen -> (a, StdGen)) -> IO aSource
Uses the supplied function to get a value from the
current global random generator, and updates the global
generator with the new generator returned by the
function. For example, rollDice gets a random integer
between 1 and 6:
rollDice :: IO Int
rollDice = getStdRandom (randomR (1,6))
Of course, printing to the screen can be a pain in the neck.The cultural aversion to IO is Haskell's largest psychological problem. Newbies learn to avoid IO at all costs, and then never back off from the precipice and realize that sometimes IO is with the price you pay.
But yeah, it's harder to do IO in Haskell than non-pure languages, and you have to bend your brain to a different model.
In the worst case, though, you can just run your entire program in the IO monad, and then factor out your pure code bit by bit. None(?) of the Haskell tutorials will tell you do this, but it is the gentlest way to get real work done as a new-to-intermediate Haskeller.