在haskell中随机生成加权数

时间:2015-10-01 19:51:03

标签: haskell

我是Haskell的新手,我正在尝试为Sudoku中的任意单元格生成随机加权数字

90% of the time, it should generate Nothing
10% of the time, it should generate a random value between 1 and 9

这是我到目前为止所提出的(它没有编译)

-- cell generates an arbitrary cell in a Sudoku
-- cell :: Gen (Maybe Int)


cell = case x of 1 -> return (Just y); _ -> return Nothing
        where std = mkStdGen(100)
              (x, a) = randomR(1, 10) std
              (y, a')= randomR(1, 9) std

非常感谢任何帮助它进行编译,或指导我采用更好的方法

使用Quickcheck这就是我的方法:

-- cell generates an arbitrary cell in a Sudoku
cell :: Gen (Maybe Int)
cell = frequency [(9, return Nothing), 
               (1, do r <- choose (1,9); return (Just r))]        

-- an instance for generating Arbitrary Sudokus
instance Arbitrary Sudoku where
  arbitrary =
    do rows <- sequence [ sequence [ cell | j <- [1..9] ] | i <- [1..9] ]
       return (Sudoku rows)

1 个答案:

答案 0 :(得分:2)

如果您使用的是QuickCheck,那么您当然不希望cell达到纯值 - randomR (0,100) (mkStdGen 43434343)不是随机的,因此对您来说测试无用。

由于您使用的是QuickCheck,因此需要使用QuickCheck功能。您也不能轻易使用System.Random。只需使用(非常强大的)QuickCheck API,它具有一个函数choose :: Random a => (a,a) -> Gen a,它可以选择一个范围内的随机数,一个函数frequency :: [(Int, Gen a)] -> Gen a根据它的权重选择一个随机生成器,即可能性,并返回该生成器。您可以将cell写为:

cell :: Gen (Maybe Int)
cell = frequency 
  [ (1, Just `fmap` choose (1,9))
  , (9, return Nothing) 
  ]

然后,例如,如果您将数独游戏板定义为data Sudoku = Sudoku [[Maybe Int]],则可以使用Arbitrary轻松为其编写cell个实例:

import Control.Monad (replicateM)

instance Arbitrary Sudoku where 
  arbitrary = Sudoku `fmap` replicateM 9 (replicateM 9 cell)