这有效:
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
但是看起来很笨拙,有没有更明智的方式来组合这些生成器?它基本上会选择三只随机动物,然后随机抽取奖品,然后制作六张门票。
答案 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
我认为它看起来不错。