[Haskell-beginners] Organizing cmd line flow

Bryan Vicknair bryanvick at gmail.com
Wed Jan 30 17:16:37 CET 2013


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



More information about the Beginners mailing list