Reputation: 225
I have the some code that compile and works. And then some that don't. My concern was that the first version was soooo bloated that it crashed while running on too big arguments, so I wrote a second version with performance in mind. The second version does't even compile. Please advice.
import System.Environment (getArgs)
import Data.List (nub)
import System.Random
import Control.Applicative ( (<$>) )
import Control.Monad (replicateM)
randomItem :: [a] -> IO a
randomItem xs = (xs!!) <$> randomRIO (0, length xs - 1)
genFromMask :: [String] -> IO String
genFromMask = mapM randomItem
genMeSome :: [String] -> Int -> IO [String]
genMeSome mask n = do
glist <- replicateM (n*10) (genFromMask mask)
return $ take n $ nub glist
writeIt :: FilePath -> Int -> [String] -> IO ()
writeIt fi n mask = do
glist <- genMeSome mask n
writeFile fi $ unlines glist
maj :: String
maj = ['A'..'Z']
numa :: String
numa = ['0'..'9']
-- | Certaines regions n'utilisent aucune des plages libres
genBra :: [String]
genBra = ["VWXYZ",maj,maj," ",numa,numa,numa,numa]
genAus :: [String]
genAus = [maj,maj,maj," ",numa,numa,numa]
main :: IO ()
main = do
args <- getArgs
case args of
(mo:fi:n:_) -> case mo of
"aus" -> writeIt fi (read n) genAus
"bra" -> writeIt fi (read n) genBra
_ -> error "country is not supported"
_ -> error "wrong input, format is: genLicensePlate country file number"
And here is the second:
import System.Environment (getArgs)
import System.Random
import Crypto.Random.AESCtr (makeSystem)
import Control.Applicative ( (<$>) )
import qualified Data.Vector as V
import qualified Data.Text as T
import qualified Data.Text.IO as T
nubV :: V.Vector a -> V.Vector a
nubV va
| V.null va = V.empty
| V.any (== headV) tailV = nubV tailV
| otherwise = headV `V.cons` nubV tailV
where
headV = V.head va
tailV = V.tail va
randomItem :: RandomGen g => g -> V.Vector a -> (a,g)
randomItem g xs =
(xs V.! fst shamble, snd shamble)
where
shamble = randomR (0, V.length xs - 1) g
genFromMask :: RandomGen g => g -> V.Vector (V.Vector a) -> V.Vector a
genFromMask g xs =
if V.null xs
then V.empty
else fst paket `V.cons` genFromMask (snd paket) (V.tail xs)
where
paket = randomItem g (V.head xs)
genMeSome :: RandomGen g => g -> V.Vector (V.Vector a) -> Int -> V.Vector (V.Vector a)
genMeSome g mask n =
V.take n $ nubV $ V.replicateM (n*10) (genFromMask g mask)
writeIt :: RandomGen g => g -> FilePath -> Int -> V.Vector (V.Vector a) -> IO ()
writeIt g fi n mask =
T.writeFile fi $ T.unlines $ T.pack $ V.toList (V.map V.toList $ genMeSome g mask n)
maj = V.fromList ['A'..'Z']
num a = V.fromList ['0'..'9']
vspa = V.fromList " "
vtir = V.fromList "-"
-- | Certaines regions n'utilisent aucune des plages libres
genBra = V.fromList [static,maj,maj,vspa,numa,numa,numa,numa]
where
static = V.fromList "VWXYZ"
genAus = V.fromList [maj,maj,maj,vspa,numa,numa,numa]
main :: IO ()
main = do
g <- makeSystem
args <- getArgs
case args of
(mo:fi:n:_) -> case mo of
"aus" -> writeIt g fi (read n) genAus
"bra" -> writeIt g fi (read n) genBra
_ -> error "country is not supported"
_ -> error "wrong input, format is: genLicensePlate country file number"
I am trying to generate fake licenses plates, to populate an anonymous database.
EDIT1:
Here are the errors:
genLicensePlate.hs:22:12:
No instance for (Eq a)
arising from a use of `=='
In the first argument of `V.any', namely `(== headV)
In the expression: V.any (== headV) tailV
In a stmt of a pattern guard for
an equation for `nubV':
V.any (== headV) tailV
genLicensePlate.hs:48:52:
Couldn't match expected type `Char' with actual type
Expected type: V.Vector Char
Actual type: V.Vector [a]
In the first argument of `V.toList', namely
`(V.map V.toList $ genMeSome g mask n)'
In the second argument of `($)', namely
`V.toList (V.map V.toList $ genMeSome g mask n)'
EDIT2:
So the general idea is to use a mask to generate random Strings. Like myFunc g [['A'..'Z'],['A'..'Z']] gives AA or ZZ or BA or FG etc... Then I use this function to make a lot of those strings based on the mask. After that I removes duplicate and take as many as needed (since I generate 10 times the number asked even with duplicate I am OK). Finaly I drop it on a file.
I hope it is more clear.
Kind regards, Sar
Upvotes: 1
Views: 202
Reputation: 183873
nubV
needs an Eq
constraint, since it compares elements (but you really should use a Set
or HashSet
or so to get a better algorithm)
nubV :: Eq a => V.Vector a -> V.Vector a
nubV va
| V.null va = V.empty
| V.any (== headV) tailV = nubV tailV
| otherwise = headV `V.cons` nubV tailV
where
headV = V.head va
tailV = V.tail va
And in writeIt
, you lack a map
,
writeIt :: RandomGen g => g -> FilePath -> Int -> V.Vector (V.Vector a) -> IO ()
writeIt g fi n mask =
T.writeFile fi $ T.unlines $ map T.pack $ V.toList (V.map V.toList $ genMeSome g mask n)
-- ^^^
since you get a list of lists of Char
from V.toList (V.map V.toList $ genMeSome g mask n)
.
That fixes the two reported errors.
Upvotes: 3