5

I'm working on learning some Haskell (please excuse the newbie error)-

This routine errors out. My understanding of the do & <- syntax is that they extract the non-Monad type from the monad. So that understanding is flawed: what's the correct understanding here?

exister :: String -> Bool exister path = do fileexist <- doesFileExist path direxist <- doesDirectoryExist path return fileexist || direxist 

error

ghc -o joiner joiner.hs joiner.hs:53:2: Couldn't match expected type `Bool' against inferred type `m Bool' In the first argument of `(||)', namely `return fileexist' In the expression: return fileexist || direxist In the expression: do { fileexist <- doesFileExist path; direxist <- doesDirectoryExist path; return fileexist || direxist } 
3
  • 8
    You cannot escape the IO monad. Commented Aug 1, 2011 at 20:48
  • 1
    Judging by your comment below, you may want to check out this question and its answers: stackoverflow.com/questions/6628748/… (we really need a proper FAQ for this) Commented Aug 1, 2011 at 20:55
  • I think it may be helpful to point out that Haskell's return is not much like "return" in most languages. If you want a function that takes a number n, and "returns" n+1, you write f n = n + 1, not f n = return n+1. Commented Aug 2, 2011 at 0:30

2 Answers 2

11

First problem: The line return fileexist || direxist is parsed as (return fileexist) || direxist, and you can’t pass m Bool as the first argument of ||. Change it to return (fileexist || direxist).

Second problem: You claim the return type of exister is Bool, but the compiler infers that it must be IO Bool. Fix it. (The do and <- syntax let you extract the a value from an m a value, but only if you promise to return an m a value.)

Sign up to request clarification or add additional context in comments.

6 Comments

I assure you, I want exister to return a Bool, not a IO Bool.
@Paul: That's not possible. Whether a file/directory exists or not, depends on the environment. It is an impure function, and therefore it must return IO Bool. A pure function must always return the same output given the same input. That's clearly not the case here.
@hammar: so if my whole program is oriented around sucking data from the hard disk/network, munging it, and sending it out, I have to dork with the IO monad in all my computations?
@Paul Your computations can be pure, but your operation is clearly IO. For example, a main routine that lives in the IO monad can get data from disk or network (ex: x <- getData) and pass that data to a pure computation (ex: let result = computationOn x) then send the result out (sendOnNetwork result).
@Paul Nathan, I ran into your exact issues when I was starting. Fortunately, the learning curve is worth the work.
|
5

The type you've given exister :: String -> Bool is for a function that returns an ordinary, non-monadic Bool. The actions you're performing, doesFileExist path and doesDirectoryExist path have type IO Bool, so the m Bool in the error message really means IO Bool. If you change the type of exister to return IO Bool instead, the type will be what you intend.

Also, in the last line, you need some more parens: return (fileexist || direxist).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.