Created
May 11, 2011 22:12
-
-
Save ijt/967505 to your computer and use it in GitHub Desktop.
Simple example of monadic IO with QuickCheck in Haskell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env runhaskell | |
-- Synopsis: | |
-- $ cabal install QuickCheck | |
-- $ runhaskell io_quickcheck_example.hs | |
-- | |
-- Author: Issac Trotts <[email protected]> | |
import Directory | |
import System.Environment | |
import System.Process | |
import System.Exit | |
import Test.QuickCheck (Property, quickCheck, (==>)) | |
import Test.QuickCheck.Monadic (assert, monadicIO, run) | |
main = do | |
putStrLn "addThenClearMakesClear" | |
quickCheck addThenClearMakesClear | |
putStrLn "addNewIsIdempotent" | |
quickCheck addNewIsIdempotent | |
-- Add some strings to /tmp/foo | |
add :: [String] -> IO () | |
add strings = do | |
-- Have to write then rename to work around lazy IO. | |
oldStrings <- get | |
writeFile "/tmp/foo2" $ unlines $ oldStrings ++ strings | |
renameFile "/tmp/foo2" "/tmp/foo" | |
-- Add some strings to /tmp/foo that were not already there | |
addNew :: [String] -> IO () | |
addNew strings = do | |
oldStrings <- get | |
add [s | s <- strings, s `notElem` oldStrings && s /= ""] | |
-- Get all the strings in /tmp/foo | |
get :: IO [String] | |
get = readProcessOrDie "cat" ["/tmp/foo"] "" >>= return . lines | |
-- Clear /tmp/foo | |
clear :: IO () | |
clear = writeFile "/tmp/foo" "" | |
readProcessOrDie :: String -> [String] -> String -> IO String | |
readProcessOrDie cmd args input = do | |
(code, stdout, _) <- readProcessWithExitCode cmd args input | |
case code of | |
ExitFailure i -> error $ ("Command failed with status " ++ show i ++ | |
": " ++ cmd ++ show args) | |
ExitSuccess -> return stdout | |
addThenClearMakesClear :: [String] -> Property | |
addThenClearMakesClear strings = monadicIO $ do | |
run $ add strings | |
run $ clear | |
contents <- run $ get | |
assert $ contents == [] | |
addNewIsIdempotent :: [String] -> Property | |
addNewIsIdempotent strings = (and $ map ('\n' `notElem`) strings) ==> monadicIO $ do | |
run $ clear | |
run $ addNew strings | |
contents1 <- run $ get | |
run $ addNew strings | |
contents2 <- run $ get | |
assert $ contents1 == contents2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FYI to anyone else who happens to find this Gist.
Line 9
import Directory
is supposed to beimport System.Directory
. After fixing it, this should run without issues.