Gang Chen
Gang Chen

Reputation: 23

haskell program compile error about hClose temph

The error message show below. If remove the line in code hClose temph, the program can be compiled successfully.

tempfile.hs:85:8: error:
    • Couldn't match type ‘a’ with ‘()’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          withTempFile :: forall a.
                          String -> (FilePath -> Handle -> IO a) -> IO a
        at tempfile.hs:62:1-62
      Expected type: IO a
        Actual type: IO ()
    • In a stmt of a 'do' block: hClose temph
      In the expression:
        do tempdir <- getTemporaryDirectory
           (tempfile, temph) <- openTempFile tempdir pattern
           func tempfile temph
           hClose temph
      In an equation for ‘withTempFile’:
          withTempFile pattern func
            = do tempdir <- getTemporaryDirectory
                 (tempfile, temph) <- openTempFile tempdir pattern
                 func tempfile temph
                 ....
    • Relevant bindings include
        func :: FilePath -> Handle -> IO a (bound at tempfile.hs:63:22)
        withTempFile :: String -> (FilePath -> Handle -> IO a) -> IO a
          (bound at tempfile.hs:63:1)
   |
85 |        hClose temph
   |        ^^^^^^^^^^^^

The code

withTempFile :: String -> (FilePath -> Handle -> IO a) -> IO a
withTempFile pattern func =
    do -- The library ref says that getTemporaryDirectory may raise on
       -- exception on systems that have no notion of a temporary directory.
       -- So, we run getTemporaryDirectory under catch.  catch takes
       -- two functions: one to run, and a different one to run if the
       -- first raised an exception.  If getTemporaryDirectory raised an
       -- exception, just use "." (the current working directory).
       --tempdir <- catch (getTemporaryDirectory) (\_ -> return ".")
       tempdir <- getTemporaryDirectory
       (tempfile, temph) <- openTempFile tempdir pattern 

       -- Call (func tempfile temph) to perform the action on the temporary
       -- file.  finally takes two actions.  The first is the action to run.
       -- The second is an action to run after the first, regardless of
       -- whether the first action raised an exception.  This way, we ensure
       -- the temporary file is always deleted.  The return value from finally
       -- is the first action's return value.
       --finally (func tempfile temph) 
       --        (do hClose temph
       --            removeFile tempfile)
       func tempfile temph
       -- putStrLn temph
       hClose temph
       --removeFile tempfile

Upvotes: 0

Views: 53

Answers (1)

Since the hClose is last, that's what comes out of the do block. You need the result of func to come out of the do block, so do this instead:

       rv <- func tempfile temph
       hClose temph
       return rv

You still need to do more work to make it exception-safe, but that's enough to make it compile and work right on the happy path.

Upvotes: 4

Related Questions