文字列を選択した後、再度繰り返すことができないように、文字列を生成するという問題を考えてみましょう。この作業のために、QuickCheck
のGen
関数を使用したいと思います。QuickCheckを使用した文字列プールからのランダムな文字列の生成
私が書こうとしている関数のタイプを見ると、それは状態モナドのように見えます。私は別のモナド、すなわちGen
を使用しているので、モナドの中にあります。私はStateT
を使って私の最初の試みを書いた。
arbitraryStringS :: StateT GenState Gen String
arbitraryStringS =
mapStateT stringGenS get
:この実装について私にトラブル
newtype GenState = St {getStrings :: [String]}
deriving (Show)
removeString :: String -> GenState -> GenState
removeString str (St xs) = St $ delete str xs
stringGenS :: Gen (a, GenState) -> Gen (String, GenState)
stringGenS genStSt =
genStSt >>= \(_, st) ->
elements (getStrings st) >>= \str ->
return (str, removeString str st)
何かが、私はstringGenS
の最初の要素を使用していないという事実です。次に、私の最終目標は、リソースプール(文字列だけでなく)を使用するJSON値用のランダムジェネレータを定義することです。 StateT
を使用すると、私はこれを達成するためのより良い方法があるのかどうか迷った、または、そのような複雑さは、既存のモナドのステートフルバリアントを定義するに固有の
など、QuickCheck
さんelements
、listOf
の「ステートフル」の変種を実装するために私を導きました。
私は、作成された 'Strings'を格納するために、あるいは少なくともシードを作成し、シード/' String'の 'Set'のメンバシップのために各シード/生成された文字列を比較します。 – epsilonhalbe
別の選択肢は、文字列の有限集合しか持たない場合は、uuidを使用して "おそらく"最もユニークな文字列を生成することができます - 結局文字列がなくなり、大きな基底集合を組み合わせて回避することができます"真の一意性"が必要な場合は、基数セット+自然数のような無限集合にして、それを結合します。 – epsilonhalbe
文字列はリソースプールから取得することが重要です。これは、一部のデータベースに存在するデータを使用してテストを生成するために使用できます。 –