read-env-var-0.1.0.1: src/System/ReadEnvVar.hs
{-# LANGUAGE CPP #-}
{-|
Module : System.ReadEnvVar
Copyright : (c) Dennis Gosnell, 2016
License : BSD-style (see LICENSE file)
Maintainer : cdep.illabout@gmail.com
Stability : experimental
Portability : POSIX
This Haskell module exports functions for safely reading environment variables.
-}
module System.ReadEnvVar
( readEnvVar
, readEnvVarDef
, lookupEnvDef
) where
#if __GLASGOW_HASKELL__ < 710
-- We don't need this import for GHC 7.10 as it exports all required functions
-- from Prelude
import Control.Applicative
#endif
import Data.Maybe (fromMaybe)
import Data.String (IsString(fromString))
import System.Environment (lookupEnv)
import Text.Read (readMaybe)
-- | Lookup a value from an environment variable and read it in with
-- 'readMaybe'. If the environment variable doesn't exist, or it can't be
-- 'read', use the default value.
--
-- Note that this does not read string values as one would expect.
--
-- >>> import System.Environment (setEnv)
-- >>> setEnv "TEST_ENV_VAR1" "1000"
-- >>> readEnvVarDef "TEST_ENV_VAR1" 5 :: IO Int
-- 1000
-- >>> readEnvVarDef "THIS_ENV_VAR_WILL_NOT_EXIST" 5 :: IO Int
-- 5
-- >>> setEnv "TEST_ENV_VAR2" "some string 1"
-- >>> readEnvVarDef "TEST_ENV_VAR2" "def val" :: IO String
-- "def val"
-- >>> setEnv "TEST_ENV_VAR3" "\"some string 1\""
-- >>> readEnvVarDef "TEST_ENV_VAR3" "def val" :: IO String
-- "some string 1"
readEnvVarDef :: Read a
=> String -- ^ environment variable to lookup
-> a -- ^ default value to use if the environment variable
-- either does not exist, or cannot be 'read'
-> IO a
readEnvVarDef envVar def = fromMaybe def <$> readEnvVar envVar
-- | Lookup a value from an environment variable and read it in with
-- 'readMaybe'.
--
-- Note that this does not read string values as one would expect.
--
-- >>> import System.Environment (setEnv)
-- >>> setEnv "TEST_ENV_VAR" "2000"
-- >>> readEnvVar "TEST_ENV_VAR" :: IO (Maybe Int)
-- Just 2000
-- >>> readEnvVar "THIS_ENV_VAR_WILL_NOT_EXIST" :: IO (Maybe Int)
-- Nothing
-- >>> setEnv "TEST_ENV_VAR2" "some string 1"
-- >>> readEnvVar "TEST_ENV_VAR2" :: IO (Maybe String)
-- Nothing
-- >>> setEnv "TEST_ENV_VAR3" "\"some string 1\""
-- >>> readEnvVar "TEST_ENV_VAR3" :: IO (Maybe String)
-- Just "some string 1"
readEnvVar :: Read a
=> String -- ^ environment variable to lookup
-> IO (Maybe a)
readEnvVar = fmap (>>= readMaybe) . lookupEnv
-- | Like 'lookupEnv' but take a default value.
--
-- >>> import System.Environment (setEnv)
-- >>> setEnv "TEST_ENV_VAR" "foo"
-- >>> lookupEnvDef "TEST_ENV_VAR" "bar" :: IO String
-- "foo"
-- >>> lookupEnvDef "THIS_ENV_VAR_WILL_NOT_EXIST" "bar" :: IO String
-- "bar"
lookupEnvDef :: IsString a
=> String -- ^ environment variable to lookup
-> a -- ^ default value to use if environment variable not defined
-> IO a
lookupEnvDef envVar defaultValue =
pure . maybe defaultValue fromString =<< lookupEnv envVar