
I have an executable, which gets a file path from the command line, and passes it to this function:: createDb :: FilePath -> IO () createDb fpath = do fileExists <- doesFileExist fpath if fileExists then putStrLn "File already exists" else do parDirExists <- parentDirExists fpath if parDirExists then do con <- openCon (Config fpath) create con closeCon con putStrLn $ "created db @ " ++ fpath else putStrLn "parent dir doesn't exist" 2 checks: File exists? Parent dir exist? But already, the code is quite nested. How can I refactor this so that a few if expressions that check an IO action doesn't result in very deep nesting of the code? Is there a pattern here that I can use? I read somewhere about wrapping a common pattern like this into a Monad such that it will somehow signal to the main function that we can't proceed, but being an absolute beginner coming from Python, I would need some help with that. Perhaps exceptions are what I'm looking for since I am working with IO, but that is what I would do in Python, so I instinctively assume it's done differently in Haskell :) In Python, I might write something like this:: def createDb(fpath): if doesFileExists(fpath): raise FileExistsError(fpath) if not parDirExists(fpath): return ParentDirNoExistsError(fpath) con = openCon(Config fpath) create(con) closeCon(con) Is there any way to get closer to the following? I think this is much clearer, but perhaps I'm missing a much larger point in how this should be done in Haskell:: createDb fpath = do checkFileExists fpath checkParentDirExists fpath con <- openCon (Config fpath) create con closeCon con