簡體   English   中英

QuickCheck Haskell-生成隨機彩票

[英]QuickCheck Haskell - generating random lottery tickets

這有效:

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

但是看起來很笨拙,是否有更明智的方式組合這些發電機? 它基本上會選擇三只隨機動物,然后隨機抽取獎品,然后制作六張門票。

正如@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別名replicateM這是在這種情況下稍微更具有可讀性。

這可能會導致類似:

{-# OPTIONS_GHC -Wall #-}

module Lottery where

import Test.QuickCheck

type Animal = String
data Ticket = Ticket [Animal] Int

pticket :: Ticket -> String
pticket (Ticket ts prz) = unwords ts ++ ' ':show prz

tickets :: Gen [Ticket]
tickets = vectorOf 6 (oneof [winner, loser])
  where winner = Ticket <$> (replicate 3 <$> animal) <*> prize
        loser  = Ticket <$> (vectorOf 3 animal)      <*> prize
        animal = elements ["tiger","rabbit","dragon","snake","rat","ox",
                           "pig","sheep","horse","monkey","dog"]
        prize  = choose (10,1000)

main :: IO ()
main = print . map pticket =<< generate tickets

我認為看起來不錯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM