考慮從一組可能的字符串中生成字符串的問題,這樣一旦選擇字符串,就不能再次重複。對於這個任務,我想使用QuickCheck
的Gen
函數。使用QuickCheck從字符串池中生成隨機字符串
如果我看看我正在編寫的函數的類型,它看起來非常像狀態monad。由於我正在使用另一個monad,即Gen
,在州monad中。我使用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
等
我想知道是否有實現這一目標的一個更好的辦法,或者這樣的複雜性是與生俱來的,以確定現有的單子的狀態變量的「狀態」的變種。
我會以另一種方式來做 - 存儲創建的「字符串」 - 或者至少是種子,並比較每個種子/生成的字符串以獲得種子/字符串的「集合」中的成員資格。 – epsilonhalbe
另一種選擇是使用uuid來生成「最可能」唯一的字符串,如果您只有一組有限的字符串 - 最終用完字符串,可以通過組合大型基本組來解決 - 但仍然可以運行到重複的字符串 - 如果你需要「真正的唯一性」,我會去一個基本集合+像自然數字這樣的無限集合並結合。 – epsilonhalbe
字符串來自資源池很重要。這可用於使用某些數據庫中存在的數據生成測試。 –