Created
July 8, 2013 16:32
-
-
Save ytaras/5950348 to your computer and use it in GitHub Desktop.
Getting environment variable in type-safe and composable way
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Env where | |
import System.IO.Error (isDoesNotExistError) | |
import GHC.IO.Exception (IOException) | |
import System.Environment (getEnv) | |
import Control.Monad.Error (catchError, Error, ErrorT) | |
import Control.Monad ((>=>), liftM) | |
-- Error handler | |
data GenericError = | |
-- wrapper for IOExceptions | |
IOError IOException | |
deriving Show | |
-- Type synonym for non-IO actions that may throw error | |
type ThrowsError = Either GenericError | |
-- Type synonim for IO actions that throw error | |
type ThrowsErrorIO a = IO (ThrowsError a) | |
-- From type you may say - it performs IO, may throw IO, but if | |
-- succeds - return String | |
getEnvE :: String -> ThrowsErrorIO String | |
getEnvE a = catchError -- executes first argument, but if it returns | |
-- error, it is passed to second argument | |
(liftM Right $ getEnv a) -- liftM makes from | |
-- (String -> Either a String) function of type | |
-- IO String -> IO (Either aString) | |
(return . Left . IOError) -- point-free geclaration, type | |
-- here is (IOException -> (IO (Either IOException b))) | |
-- Only one of possible options, not necessary the best one | |
getValueOrEmpty :: ThrowsError String -> ThrowsError String | |
getValueOrEmpty err@(Left (IOError e)) | isDoesNotExistError e = Right "" | |
getValueOrEmpty x = x -- No-op | |
-- Long names are just for this example. in RW it would be something | |
-- more sane | |
getEnvValueOrEmpty :: String -> ThrowsErrorIO String | |
getEnvValueOrEmpty e = do -- We're inside IO | |
res <- getEnvE e -- res is ThrowsError String | |
return $ getValueOrEmpty res -- return transforms ThrowsError String | |
-- into ThrowsErrorIO String |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment