如何组合任意和IO monad?

时间:2017-12-06 00:29:48

标签: haskell monads quickcheck

我正在尝试编写一个程序,该程序将Arbitrary实例生成的数据列表写入文件,但我在组合ArbitraryIO 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

如何将任意生成的列表打印到文件中?

2 个答案:

答案 0 :(得分:4)

正如Test.QuickCheck.Gen告诉您的那样,您可以使用QuickCheck-GenT中的GenT。只要GenT mMonadIOm就是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]的东西,除非你的实际应用程序为类型推断提供了足够的上下文。