-2

我正在使用 Real World Haskell 书。该声明

ghci> import Test.QuickCheck
ghci> generate 10 (System.Random.mkStdGen 2) arbitrary :: [Bool]

结果是

<interactive>:8:1: error:
* Couldn't match expected type `StdGen -> Gen a1 -> [Bool]'
              with actual type `IO a0'
* The function `generate' is applied to three arguments,
  but its type `Gen a0 -> IO a0' has only one
  In the expression: generate 10 (mkStdGen 2) arbitrary :: [Bool]
  In an equation for `it':
      it = generate 10 (mkStdGen 2) arbitrary :: [Bool]

如果我正确阅读错误,似乎“System.Random.mkStdGen 2”现在正在生成一个单子?我如何让这个声明起作用?

编辑:添加了导入语句以澄清

4

1 回答 1

2

您收到的错误消息的一个关键部分在这里:

* The function `generate' is applied to three arguments,
  but its type `Gen a0 -> IO a0' has only one

这就是说generate应该只取一个元素,但你给了它三个。具体来说,您已经给出了10,System.Random.mkStdGen 2arbitrary. 仅通过查看类型,似乎很明显,获得工作程序的最佳选择是删除前两个参数以获得:

generate arbitrary :: IO [Bool]

但是,我猜你有理由投入10mkStdGen 2是吗?也许您想生产 10 Bools(或 10 [Bool]?)并使用您自己的自定义种子?你不能只是在一个函数上抛出更多的参数来让它做你想做的事情,但是如果你遵循类型,你就会到达那里。

首先,使用自定义种子。为此,我们需要放弃generate并制作我们自己的generateWithSeed

import Test.QuickCheck.Random (mkQCGen)

-- | Run a generator. The size passed to the generator is always 30;
-- if you want another size then you should explicitly use 'resize'.
generateWithSeed :: Int -> Gen a -> IO a
generateWithSeed seed (MkGen g) =
  do r <- mkQCGen seed
     return (g r 30)

获得多个结果实际上更容易——我们可以使用replicateM

import Control.Monad (replicateM)

generateMultipleWithSeed :: Int -> Int -> Gen a -> IO [a]
generateMultipleWithSeed n seed g = generateWithSeed seed (replicateM n g)

现在您可以运行原始行(尽管类型注释略有不同):

generateMultipleWithSeed 10 2 (arbitrary :: Gen Bool)
于 2021-03-28T00:16:19.803 回答