Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You would be better off removing the file and simply recovering if it does not exist:</p> <pre><code>import Prelude hiding (catch) import System.Directory import Control.Exception import System.IO.Error hiding (catch) removeIfExists :: FilePath -&gt; IO () removeIfExists fileName = removeFile fileName `catch` handleExists where handleExists e | isDoesNotExistError e = return () | otherwise = throwIO e </code></pre> <p>This avoids the race condition of someone deleting the file between your code checking whether it exists and deletes it. It might not matter in your case, but it's good practice anyway.</p> <p>Note the <code>import Prelude hiding (catch)</code> line — this is because the Prelude contains older functions from exception handling which are now deprecated in favour of Control.Exception, which also has a function named <code>catch</code>; the import line simply hides the Prelude's <code>catch</code> in favour of <a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Exception.html">Control.Exception</a>'s.</p> <p>However, that still leaves your more fundamental underlying question: how do you write conditionals in <code>IO</code>?</p> <p>Well, in this case, it would suffice to simply do</p> <pre><code>when fileExists $ removeFile filename </code></pre> <p>(using <a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Monad.html#v%3awhen">Control.Monad.when</a>). But it's helpful here, as it usually is in Haskell, to look at the types.</p> <p>Both branches of a conditional must have the same type. So to fill in</p> <pre><code>if fileExists then removeFile filename else ??? </code></pre> <p>we should look at the type of <code>removeFile filename</code>; whatever <code>???</code> is, it has to have the same type.</p> <p><a href="http://hackage.haskell.org/packages/archive/directory/latest/doc/html/System-Directory.html#v%3aremoveFile">System.Directory.removeFile</a> has the type <code>FilePath -&gt; IO ()</code>, so <code>removeFile filename</code> has the type <code>IO ()</code>. So what we want is an IO action with a result of type <code>()</code> that does nothing.</p> <p>Well, the purpose of <code>return</code> is to construct an action that has no effects, and just returns a constant value, and <code>return ()</code> has the right type for this: <code>IO ()</code> (or more generally, <code>(Monad m) =&gt; m ()</code>). So <code>???</code> is <code>return ()</code> (which you can see I used in my improved snippet above, to do nothing when <code>removeFile</code> fails because the file doesn't exist).</p> <p>(By the way, you should now be able to implement <code>when</code> with the help of <code>return ()</code>; it's really simple :))</p> <p>Don't worry if you find it hard to get into the Haskell way of things at first — it'll come naturally in time, and when it does, it's very rewarding. :)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload