使用向量来操作Chars而不是列表

时间:2013-02-27 23:00:37

标签: haskell

我有一些编译和工作的代码。然后一些没有。 我担心的是第一个版本是太膨胀了,它在运行太大的争论时崩溃了,所以我写了第二个版本,考虑到了性能。 第二个版本甚至不编译。请指教。

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"

这是第二个:

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"

我正在尝试生成虚假的牌照,以填充匿名数据库。

EDIT1:

以下是错误:

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:

所以一般的想法是使用掩码来生成随机字符串。 像myFunc g [['A'..'Z'],['A'..'Z']]给出AA或ZZ或BA或FG等...... 然后我使用这个函数根据掩码制作了很多这些字符串。 之后,我删除了副本,并根据需要采取尽可能多的数量(因为我生成10倍的数量,即使重复,我也可以)。 最后我把它放在一个文件上。

我希望它更清楚。

亲切的问候, SAR

1 个答案:

答案 0 :(得分:3)

nubV需要Eq约束,因为它会比较元素(但您确实应该使用SetHashSet左右来获得更好的算法)

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

writeIt中,您缺少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)
                            --  ^^^

因为您从Char获得V.toList (V.map V.toList $ genMeSome g mask n)的列表列表。

修复了两个报告的错误。