I'm trying to pick up some Haskell skills so thought I'd write a random password generator to get to grips with using IO
. It was far trickier than I expected and I employed rather more trial and error than I'd have liked.
What I've ended up with works, and while I'm happy with it generally I'd like to know if this is reasonable, idiomatic Haskell or if I've done anything peculiar.
import System.Random
-- Generate a random number in closed interval [lo, hi]
random_int :: Int -> Int -> IO Int
random_int lo hi = (randomRIO (lo,hi) :: IO Int)
-- Generate a random character from an internal alphabet
random_char :: IO Char
random_char = do
index <- random_int 0 $ (length alphabet) - 1
return $ alphabet !! index
where alphabet = ['A'..'Z'] ++
['a'..'z'] ++
['0'..'9'] ++
"!\"£$%^&*()-_+={}[]:;@'~#|\\<,>.?/'"
-- Generate a random password of given length
random_password :: Int -> IO String
random_password length =
sequence $ map (\x -> random_char) [1..length]
main :: IO ()
main = random_password 8 >>= putStrLn
The implementation of random_password
feels odd and hacky, but I struggled to find another way to create an array of results from successive invocations of random_char
or any way to avoid the need for sequence
. Is it hacky?