I think your idea of creating that library is pretty cool!
I’ve read through it all and have some comments:
The function signatures overall aren’t very easy to understand when the types and function name are put together.
What is this supposed to do? Why do I pass three Strings to get a random string in IO ?
getRandomString :: String -> String -> String -> IO String
And more examples like this…
getRandomIntss :: String -> String -> String -> Int -> IO [Int]
...
Sometimes, defining a type synonym can help make things clearer
Second, you rely a lot on Strings and Ints, but algebraic data types are amazing, and perhaps you could give more use to them.
The People
module is a prime example to use a data type definition
data Person = Person String String Int
-- In your current model of "passing a lang to every function and return the value in IO"
getManyPersons :: String -> IO [Person]
getManyPersons = ...
-- And then you could, e.g. define all other functions through that one
getManyFirstNames :: String -> IO [String]
getManyFirstNames lang = do
people <- getManyPersons lang
return $ map (\(Person name _ _) -> name) people
And lastly, and probably most importantly, all functions are unnecessarily in IO because you read data from a file every time a function is called. This also requires all functions to have parameters like the language. This could be abstracted away, and passed around implicitly. Think of a Faker
Monad
that could be used without IO (and just require IO to run it) – i.e., you read the data for a language once, and then pass it around – all faker calls can access the already loaded data for the chosen language. (Passing around a constant state is a common idiom, see the Reader Monad)
I’ll write what things could look like if you abstracted some concepts through a Monad instance:
fakeFirstAndLastNames :: Faker [(String, String)]
fakeFirstAndLastNames = do
firstNames <- getManyFirstNames 10
lastNames <- getManyLastNames 10
return $ zip firstNames lastNames
main :: IO ()
main = do
names <- runFaker "en_us" fakeFirstAndLastNames
forM_ print names
The implementation should be a part 2 of this answer, it’s already too long, let us know … 