Unsafe IO Or: Haskeline and Directories

160 Views Asked by At

DISCLAIMER: I am somewhat new to Haskell.

I am writing an interpreter, or, in this context, a REPL. For that purpose I am using haskeline, which is nice for REPLs. It has the capability of storing the command line history within a file, which is also nice.

One problem I came across while working with it, though, is that it does not seem to expand "~" to the home directory, which means that I have to retrieve the home directory manually.

I could do it like this (and currently do):

-- | returns a fresh settings variable
addSettings :: Env -> Settings IO
addSettings env = Settings { historyFile = Just getDir
                           , complete = completeWord Nothing " \t" $
                                        return . completionSearch env
                           , autoAddHistory = True
                           }
    where
        getDir :: FilePath
        getDir = unsafePerformIO getHomeDirectory ++ "/.zepto_history"

But that uses unsafePerformIO, which makes me cringe. Do you know of a good and clean workaround that does not involve rewriting the whole function? This can be a haskeline feature I do not know of or something I just did not see.

Telling me there is no way around rewriting and rethinking it all is fine, too.

EDIT:

I know unsafePerformIO is bad, that's why it makes me cringe. If you are new to Haskell and reading this question right now: Just pretend it is not there.

1

There are 1 best solutions below

0
On BEST ANSWER

A better approach would be to generate the Settings object inside IO, instead of the other way around, so to speak:

addSettings :: Env -> IO (Settings IO)
addSettings = do
    getDir <- fmap (++ "/.zepto_history") getHomeDirectory
    return $ Settings
        { historyFile = Just getDir
        , complete = completeWord Nothing " \t" $ return . completionSearch env
        , autoAddHistory = True
        }

This will no doubt require some changes in your current software, but this would be considered the "right" way to go about this.