2017-12-06 7 views
3

Ich versuche, ein Programm zu schreiben, das in eine Datei eine Liste von Daten schreibt, die von einer Arbitrary Instanz generiert werden, und ich habe Probleme beim Kombinieren der Arbitrary und IO Monaden.Wie kombiniere ich Arbitrary und IO Monaden?

Eine vereinfachte Version von dem, was ich versuche, wird unten gezeigt.

main = do 
    let n = 10 
    list <- vector n 
    writeFile "output.txt" (unlines $ show <$> list) 

Dies führt zu einer Art Fehler, da writeFile s Gen Monade 's IO Monade nicht vector überein'.

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) } 

Ich habe versucht, liftIO diese Art Konflikt zu beheben verwenden, aber es scheint, dass dies nicht auf Grund Gen funktioniert eine MonadIO Instanz fehlt.

main = do 
    let n = 10 
    list <- vector n :: Gen [Integer] 
    liftIO $ writeFile "output.txt" (unlines $ show <$> list) 

gibt den Fehler

TestCases.hs:32:3: error: 
    • No instance for (MonadIO Gen) arising from a use of ‘liftIO’ 
    • In a stmt of a 'do' block: 
     liftIO $ writeFile "output.txt" (unlines $ show <$> list) 
     In the expression: 
     do { let n = 10; 
      list <- vector n :: Gen [Integer]; 
      liftIO $ writeFile "output.txt" (unlines $ show <$> list) } 
     In an equation for ‘main’: 
      main 
      = do { let n = ...; 
        list <- vector n :: Gen [Integer]; 
        liftIO $ writeFile "output.txt" (unlines $ show <$> list) } 

Wie kann ich eine Arbitrary-generierte Liste in eine Datei drucken?

Antwort

4

Wie Test.QuickCheck.Gen sagt Ihnen, können Sie GenT von QuickCheck-GenT verwenden. GenT m ist eine MonadIO Instanz wann immer m ist.

main = join . generate . runGenT $ do 
    let n = 10 
    list <- liftGen $ vector n 
    liftIO $ writeFile "output.txt" (unlines $ show <$> list) 

scheint wahrscheinlich zu arbeiten.

4

Die vector Funktion gibt Ihnen den Listengenerator, und nicht um eine bestimmte Liste:

vector :: Arbitrary a => Int -> Gen [a] 

Seit (>>=) :: Monad m => m a -> (a -> m b) -> m b, wird es nicht Sie Gen raus. Aber generate von Test.QuickCheck.Gen ist die für diese Situation geeignete Einzelwertgenerierung: generate :: Gen a -> IO a. Also generate (vector n) >>= writeFile "output.txt" . unlines . map show sollte tun, was Sie wollen (abgesehen von der Art Ambiguität: es ist nicht klar in Ihrem Beispiel für was Gen [a] Ihr Vektor wird ergeben, so vielleicht etwas wie (vector n :: Gen [Int]) hinzufügen, es sei denn, Ihre eigentliche Anwendung bietet genügend Kontext für Inferenz Typ.