我正在尝试编写一个程序,该程序将Arbitrary
实例生成的数据列表写入文件,但我在组合Arbitrary
和IO
monad时遇到问题。< / p>
我想要做的简化版本如下所示。
main = do
let n = 10
list <- vector n
writeFile "output.txt" (unlines $ show <$> list)
这会导致类型错误,因为writeFile
的{{1}} monad与IO
的{{1}} monad不匹配。
vector
我尝试使用Gen
来解决此类型不匹配问题,但由于TestCases.hs:31:3: error:
• Couldn't match type ‘IO’ with ‘Test.QuickCheck.Gen.Gen’
Expected type: Test.QuickCheck.Gen.Gen ()
Actual type: IO ()
• In a stmt of a 'do' block:
writeFile "output.txt" (unlines $ show <$> list)
In the expression:
do { let n = 10;
list <- vector n;
writeFile "output.txt" (unlines $ show <$> list) }
In an equation for ‘main’:
main
= do { let n = ...;
list <- vector n;
writeFile "output.txt" (unlines $ show <$> list) }
缺少liftIO
个实例,这似乎无效。
Gen
给出错误
MonadIO
如何将任意生成的列表打印到文件中?
答案 0 :(得分:4)
正如Test.QuickCheck.Gen
告诉您的那样,您可以使用QuickCheck-GenT
中的GenT
。只要GenT m
为MonadIO
,m
就是main = join . generate . runGenT $ do
let n = 10
list <- liftGen $ vector n
liftIO $ writeFile "output.txt" (unlines $ show <$> list)
个实例。
gollum
似乎很有效。
答案 1 :(得分:4)
vector
函数为您提供列表生成器,而不是特定列表:
vector :: Arbitrary a => Int -> Gen [a]
自(>>=) :: Monad m => m a -> (a -> m b) -> m b
以来,它不会让你离开Gen
。但是来自generate
的{{1}}适用于此情况的特定值生成:Test.QuickCheck.Gen
。所以generate :: Gen a -> IO a
应该做你想要的(除了类型歧义:在你的例子中不清楚你的向量会产生什么generate (vector n) >>= writeFile "output.txt" . unlines . map show
,所以可能添加类似Gen [a]
的东西,除非你的实际应用程序为类型推断提供了足够的上下文。