Skip to content

Instantly share code, notes, and snippets.

@ytaras
Created July 8, 2013 16:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ytaras/5950348 to your computer and use it in GitHub Desktop.
Save ytaras/5950348 to your computer and use it in GitHub Desktop.
Getting environment variable in type-safe and composable way
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