Reputation: 443
I wish to construct a random string consisting of only alphabetical characters. This is the code I have so far:
letters :: String
letters = "abcdefghijklmnopqrstuvwxyz"
{- | Generates any lower case alpha character.
-}
lowerAlpha :: Gen Char
lowerAlpha = oneof (map return letters)
getString :: Int -> String
getString 0 = []
getString n = lowerAlpha : getString (n - 1)
getString is passed a random Int between 1 and 25. Because lowerAlpha returns a Gen Char getString wont work as it expects a Char in order to build a String. Is there a way to change a Gen String to a String? This is the line of code where the problem occurs - getString n = lowerAlpha : getString (n - 1)
Upvotes: 0
Views: 356
Reputation: 120711
Is there a way to change a
Gen String
to aString
?
No, emphatically not. For some reason, people coming from other programming languages always seem to think “they're both string-kinds of types, so surely they're convertible”. Nope! Gen String
is something completely, fundamentally different from String
. The latter is just a plain data value – a list of characters. But Gen String
is a generator, an action that generates strings. Assuming this can be converted to a string is like assuming a cow can be converted to a milk bottle.
The correct thing is for course for getString
to also have a Gen
type, because generating strings is what it does.
getString :: Int -> Gen String
The question is how to implement that. Well, it's guessworking because you didn't specify what Gen
is exactly, but such type constructors in Haskell are usually applicative functors. That allows you to write
getString 0 = pure []
getString n = (:) <$> lowerAlpha <*> getString (n - 1)
As gallais remarks, this can also be written shorter as
getString n = replicateM n lowerAlpha
Upvotes: 7
Reputation: 443
Thanks for your assistance. This is what I came up with. Works well. str <- listOf (choose ('a','z'))
Upvotes: 0
Reputation: 52029
Perhaps you are looking for vectorOf
, i.e.:
import Test.QuickCheck
getString :: Int -> Gen String
getString n = vectorOf n lowerAlpha
To actually generate a random string you can use generate
(requires the IO-monad):
main = do
generate (getString 25) >>= putStrLn
or just from the GHCI repl:
ghci> generate (getString 25)
"siebrxrlvuuxdvhqwcfykqwdc"
ghci> generate (getString 3)
"rcv"
Upvotes: 3