-- Haskell98! -- at least as far as GHC implements the absence -- of LANGUAGE pragmas -- Strictness is observable, with no seq, no unsafe operations -- Implementation of the strictness test with Lazy IO module StrictnessTestLIO where import System.IO -- Any file name that one can create and not be sorry to override file_name = "/tmp/foo" prepare :: IO () prepare = writeFile file_name "xxx" is_strict :: (Int -> Int) -> IO Bool is_strict f = flip catch (\_ -> return False) $ do h <- openFile file_name ReadMode lst <- hGetContents h ns <- if f (length lst) > 0 then return True else return True writeFile file_name "" return ns main_s = prepare >> is_strict (succ :: Int -> Int) -- True main_ns = prepare >> is_strict (const 1 :: Int -> Int) -- False {- Haskell98 specifically allows for the behavior that lets us distinguish strict and non-strict functions (that is, the evaluation order in the pure code). Here is the relevant chapter and the verse from Haskell98 (PDF file found on Haskell.org) 21.2.3 File locking Implementations should enforce as far as possible, at least locally to the Haskell process, multiple- reader single-writer locking on files. That is, there may either be many handles on the same file which manage input, or just one handle on the file which manages output. If any open or semi- closed handle is managing a file for output, no new handle can be allocated for that file. If any open or semi-closed handle is managing a file for input, new handles can only be allocated if they do not manage output. Whether two files are the same is implementation-dependent, but they should normally be the same if they have the same absolute path name and neither has been renamed, for example. Warning: the readFile operation (Section 7.1) holds a semi-closed handle on the file until the entire contents of the file have been consumed. It follows that an attempt to write to a file (using writeFile, for example) that was earlier opened by readFile will usually result in failure with isAlreadyInUseError. The Report specifically warns of the possibility that an implementation that implements file locking, as encouraged by the Report, can distinguish if the entire contents has been consumed or not. The consumption happens in the pure code. Thus the pure Haskell evaluation order starts to matter for a Haskell98-compliant implementation. The code demonstrates that fact. -}