QuickCheck Haskell-生成随机彩票

时间:2018-08-26 04:15:22

标签: haskell quickcheck

这有效:

genAnimal :: Gen String
genAnimal = do
  animals <- shuffle ["tiger","rabbit","dragon","snake","rat","ox","pig","sheep","horse","monkey","dog"]
  return (head animals)

genWinner :: Gen String
genWinner = do 
  animal <- genAnimal
  prize <- choose (10::Int,1000::Int)
  return (unwords (replicate 3 animal) ++ " " ++ show prize)

genTicket :: Gen String
genTicket = do 
  animals <- replicateM 3 genAnimal
  prize <- choose (10::Int,1000::Int)
  return (unwords animals ++ " " ++ show prize)

genTickets :: Gen [String]
genTickets = do
  tickets <- replicateM 6 (oneof [genWinner, genTicket])
  return tickets

但是看起来很笨拙,有没有更明智的方式来组合这些生成器?它基本上会选择三只随机动物,然后随机抽取奖品,然后制作六张门票。

1 个答案:

答案 0 :(得分:1)

正如@AJFarmar指出的那样,您可以使用elements组合器从列表中选择一个随机元素,而不用改编版本的开头:

genAnimal :: Gen String
genAnimal = elements ["tiger","rabbit","dragon","snake","rat","ox",
                      "pig","sheep","horse","monkey","dog"]

此外,应用样式通常更简洁,特别是如果您为结合了结果的纯计算引入了辅助函数:

genPrize :: Gen Int
genPrize = choose (10,1000)

genTicket :: Gen String
genTicket = ticket <$> replicateM 3 genAnimal <*> genPrize
  where ticket animals prize = unwords animals ++ " " ++ show prize

其他一些其他改进可能来自:

  • 改变对生成器的看法,生成最后组合的单词,而不是必须unword并与空格粘合在一起的字符串;
  • 或更妙的是,引入一些数据类型以更好地为您的问题建模,并提供实用程序功能以仅在需要时以适当的String格式打印它;
  • 摆脱gen前缀的困扰,一切都变得混乱
  • 使用vectorOf的{​​{1}}别名在这种情况下更具可读性。

这可能会导致类似的情况:

replicateM

我认为它看起来不错。