me2
me2

Reputation: 3119

In Haskell, is there a way to do IO in a function guard?

For example:

newfile :: FilePath -> IO Bool
newfile x | length x <= 0 = return False
          | doesFileExist x == True = return False
          | otherwise = return True

Can this be made to work?

Upvotes: 3

Views: 2967

Answers (4)

me2
me2

Reputation: 754

This works and does what's needed:

newfile :: FilePath -> IO Bool
newfile fn = do 
    x <- runErrorT $ do
        when ((length fn) <= 0) (throwError "Empty filename")
        dfe <- liftIO $ doesFileExist fn
        when (dfe) (throwError "File already exists")
        return True
    return $ either (\_ -> False) id x

Upvotes: 5

Greg Bacon
Greg Bacon

Reputation: 139441

You're already in the IO monad, so why not use the following?

newfile :: FilePath -> IO Bool
newfile x | length x <= 0 = return False
          | otherwise = do exists <- doesFileExist x
                           return $ not exists

For applicative goodness:

import Control.Applicative

newfile :: FilePath -> IO Bool
newfile x | length x <= 0 = return False
          | otherwise = not <$> doesFileExist x

As you can see, the applicative route is even more concise than the guards you'd like to use in your question!

Upvotes: 19

yfeldblum
yfeldblum

Reputation: 65435

The type of guard clauses must be Bool. The type of doesFileExist x is IO Bool. The type mismatch means you can't do that.

Upvotes: 3

Ganesh Sittampalam
Ganesh Sittampalam

Reputation: 29100

No, there's no way to do this (short of unsafe tricks which would be completely inappropriate here).

BTW doesFileExist x == True would be better written as doesFileExist x were it possible at all.

Upvotes: 6

Related Questions