diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,12 @@
 ## MASTER
+## Dotenv 0.5.2.0
+
+* Add `loadSafeFile` to typecheck the envs.
+* Add `(--schema|-s) FILE` flag to the `dotenv` CLI tool to enable safe mode.
+* Add `(--no-schema)` flag to the `dotenv` CLI tool to disable safe mode.
+* Turn safe mode on automatically when the `.schema.yml` file is present.
+* Make `required` optional in the `.schema.yml`.
+
 ## Dotenv 0.5.1.1
 
 * Allow `.env` empty files
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@
 
 ```haskell
 import qualified Configuration.Dotenv as Dotenv
-Dotenv.loadFile False "/path/to/your/file"
+Dotenv.loadFile defaultConfig
 ```
 
 After calling `Dotenv.load`, you are able to read the values set in your
@@ -67,7 +67,7 @@
 ```
 DATABASE=postgres://${USER}@localhost/database
 ```
- 
+
 Running it on the CLI:
 
 ```
@@ -83,7 +83,7 @@
 ```
 DATABASE=postgres://$(whoami)@localhost/database
 ```
- 
+
 Running it on the CLI:
 
 ```
@@ -91,13 +91,65 @@
 postgres://myusername@localhost/database
 ```
 
+### Type checking envs
+Env variables are simple strings. However, they can represent other types like
+integers, booleans, IP addresses, emails, URIs, and so on. We provide an interface
+that performs type checking after loading the envs and before running your application.
+If the type-check succeeded the application is executed, otherwise you will get an
+error with the types that mismatch.
+
+In order to use this functionality you can use the `loadSafeFile` which takes the same
+configuration value as the `loadFile` function. Also, you need to have a `.schema.yml`
+in your current directory. This file must have the following structure:
+
+```yaml
+- name: DOTENV
+  type: bool
+  required: true
+- name: OTHERENV
+  type: bool
+- name: PORT
+  type: integer
+  required: true
+- name: TOKEN
+  type: text
+  required: false
+```
+
+It is a list of type and envs. So, in this example, `DOTENV` must have a value
+of `true` or `false` otherwise it won't be parsed as a boolean value. And envs
+like `PORT` must be any integer. Currently, we are supporting the following types:
+
+- `bool` - Accepts values `false` or `true`
+- `integer` - Accepts values of possitive integers
+- `text` - Any text
+
+**require** specifies if the env var is obligatory or not. In case you set it to true
+but do not provide it, you wil get an exception. When **required** is omited, the default
+value is `false`.
+
+**NOTE:** All the variables which are **required** in the `schema.yml` must be defined
+in the dotenvs.
+
 ## Configuration
 
-The first argument to `loadFile` specifies whether you want to
-override system settings. `False` means Dotenv will respect
+The first argument to `loadFile` specifies the configuration. You cans use
+`defaultConfig` which parses the `.env` file in your current directory and
+doesn't override your envs. You can also define your own configuration with
+the `Config` type.
+
+`False` in `configOverride` means Dotenv will respect
 already-defined variables, and `True` means Dotenv will overwrite
 already-defined variables.
 
+In the `configPath` you can write a list of all the dotenv files where are
+envs defined (e.g `[".env", ".tokens", ".public_keys"]`).
+
+In the `configExamplePath` you can write a list of all the dotenv example files
+where you can specify which envs **must be defined** until running a program
+(e.g `[".env.example", ".tokens.example", ".public_keys.example"]`). If you don't
+need this functionality you can set `configExamplePath` to an empty list.
+
 ## Advanced Dotenv File Syntax
 
 You can add comments to your Dotenv file, on separate lines or after
@@ -170,6 +222,29 @@
 current environment settings. By invoking the program `env` in place
 of `myprogram` above you can see what the environment will look like
 after evaluating multiple Dotenv files.
+
+The `--schema FILE` will get the envs configuration from the `FILE`. For instance:
+
+```shell
+$ cat .env
+PORT=123a
+$ cat .schema.yml
+- name: PORT
+  required: true
+  type: integer
+```
+
+running `dotenv` will throw:
+
+```shell
+$ dotenv -s .schema.yml "echo $PORT"
+dotenv: 1:4:
+unexpected 'a'
+expecting digit or end of input
+```
+
+**NOTE:** The flag can be omited when the `.schema.yml` is in the current working
+directory. To disable type checking add the flag `--no-schema`.
 
 ## Author
 
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -11,10 +11,11 @@
 import Options.Applicative
 import Paths_dotenv (version)
 
-import Control.Monad (void)
+import Control.Monad (void, unless)
 
 import Configuration.Dotenv (loadFile)
 import Configuration.Dotenv.Types (Config(..), defaultConfig)
+import Configuration.Dotenv.Scheme ( runSchemaChecker )
 
 import System.Process (system)
 import System.Exit (exitWith)
@@ -25,29 +26,36 @@
   , override           :: Bool
   , program            :: String
   , args               :: [String]
+  , schemaFile         :: FilePath
+  , disableSchema      :: Bool
   } deriving (Show)
 
 main :: IO ()
 main = do
   Options{..} <- execParser opts
-  void $ loadFile Config
-    { configExamplePath = dotenvExampleFiles
-    , configOverride = override
-    , configPath =
-        if null dotenvFiles
-          then configPath defaultConfig
-          else dotenvFiles
-    }
-  system (program ++ concatMap (" " ++) args) >>= exitWith
-    where
-      opts = info (helper <*> versionOption <*> config)
-        ( fullDesc
-       <> progDesc "Runs PROGRAM after loading options from FILE"
-       <> header "dotenv - loads options from dotenv files" )
-      versionOption =
-        infoOption
-          (showVersion version)
-          (long "version" <> short 'v' <> help "Show version of the program")
+  let configDotenv =
+        Config
+          { configExamplePath = dotenvExampleFiles
+          , configOverride = override
+          , configPath =
+              if null dotenvFiles
+                then configPath defaultConfig
+                else dotenvFiles
+          }
+   in do
+     void $ loadFile configDotenv
+     unless disableSchema
+       (runSchemaChecker schemaFile configDotenv)
+     system (program ++ concatMap (" " ++) args) >>= exitWith
+       where
+         opts = info (helper <*> versionOption <*> config)
+           ( fullDesc
+          <> progDesc "Runs PROGRAM after loading options from FILE"
+          <> header "dotenv - loads options from dotenv files" )
+         versionOption =
+           infoOption
+             (showVersion version)
+             (long "version" <> short 'v' <> help "Show version of the program")
 
 config :: Parser Options
 config = Options
@@ -70,3 +78,9 @@
 
      <*> many (argument str (metavar "ARG"))
 
+     <*> strOption ( long "schema"
+                      <> short 's'
+                      <> help "Set the file path for the schema.yml file"
+                      <> value ".schema.yml" )
+
+     <*> switch ( long "no-schema" <> help "Omit type checking" )
diff --git a/dotenv.cabal b/dotenv.cabal
--- a/dotenv.cabal
+++ b/dotenv.cabal
@@ -1,5 +1,5 @@
 name:                dotenv
-version:             0.5.1.1
+version:             0.5.2.0
 synopsis:            Loads environment variables from dotenv files
 homepage:            https://github.com/stackbuilders/dotenv-hs
 description:
@@ -48,6 +48,7 @@
 data-files:
   .dotenv
   .dotenv.example
+  .scheme.yml
 
 flag dev
   description:        Turn on development settings.
@@ -64,6 +65,7 @@
                        , process >= 1.4.3.0
                        , text
                        , transformers >=0.4 && < 0.6
+                       , yaml
   other-modules: Paths_dotenv
 
   hs-source-dirs:      app
@@ -79,14 +81,20 @@
                       , Configuration.Dotenv.ParsedVariable
                       , Configuration.Dotenv.Text
                       , Configuration.Dotenv.Types
+                      , Configuration.Dotenv.Scheme
+                      , Configuration.Dotenv.Scheme.Helpers
+                      , Configuration.Dotenv.Scheme.Parser
+                      , Configuration.Dotenv.Scheme.Types
 
   build-depends:         base >=4.7 && <5.0
                        , base-compat >= 0.4
+                       , directory
                        , megaparsec >= 6.0 && < 7.0
                        , process >= 1.4.3.0
                        , text
                        , transformers >=0.4 && < 0.6
                        , exceptions >= 0.8 && < 0.9
+                       , yaml
 
   if !impl(ghc >= 7.10)
     build-depends:      void         == 0.7.*
@@ -111,10 +119,17 @@
                        , Configuration.Dotenv.Types
                        , Configuration.Dotenv.Parse
                        , Configuration.Dotenv.ParsedVariable
+                       , Configuration.Dotenv.SchemeSpec
+                       , Configuration.Dotenv.Scheme.ParseSpec
+                       , Configuration.Dotenv.Scheme
+                       , Configuration.Dotenv.Scheme.Helpers
+                       , Configuration.Dotenv.Scheme.Parser
+                       , Configuration.Dotenv.Scheme.Types
 
   build-depends:       base >=4.7 && <5.0
                      , base-compat >= 0.4
                      , dotenv
+                     , directory
                      , megaparsec >= 6.0 && < 7.0
                      , hspec
                      , process >= 1.4.3.0
@@ -122,6 +137,7 @@
                      , transformers >=0.4 && < 0.6
                      , exceptions >= 0.8 && < 0.9
                      , hspec-megaparsec >= 1.0 && < 2.0
+                     , yaml
 
   if !impl(ghc >= 7.10)
     build-depends:      void         == 0.7.*
diff --git a/spec/Configuration/Dotenv/Scheme/ParseSpec.hs b/spec/Configuration/Dotenv/Scheme/ParseSpec.hs
new file mode 100644
--- /dev/null
+++ b/spec/Configuration/Dotenv/Scheme/ParseSpec.hs
@@ -0,0 +1,63 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+module Configuration.Dotenv.Scheme.ParseSpec (spec) where
+
+import Data.Either (isLeft, isRight)
+import Data.Yaml (decodeFileEither)
+import Test.Hspec
+
+import Configuration.Dotenv.Scheme.Types
+import Configuration.Dotenv.Scheme.Parser
+
+fromRight :: (Show a, Show b) => Either a b -> b
+fromRight (Right v) = v
+fromRight (Left v) = error ("Left " ++ show v ++ " constructor instead" )
+
+spec :: Spec
+spec = do
+  specInstance
+  specParse
+
+specInstance :: Spec
+specInstance = describe "parse a config env file" $
+  it "parses the env config values from a file" $
+    let expected :: [Env]
+        expected =
+            [ Env "DOTENV" EnvBool True
+            , Env "OTHERENV" EnvBool False
+            , Env "PORT" EnvInteger True
+            , Env "TOKEN" EnvInteger False
+            , Env "URL" EnvText True
+            ]
+     in do
+       actual <- decodeFileEither "spec/fixtures/.scheme.yml"
+       fromRight actual `shouldBe` expected
+
+specParse :: Spec
+specParse =
+  describe "parseEnvAs" $ do
+    context "given an integer" $ do
+      context "when the integer can be parsed" $
+        it "should return Right ()" $
+          let varContent = "123"
+              integer = EnvInteger
+           in varContent `parseEnvAs` integer `shouldSatisfy` isRight
+
+      context "when the integer can't be parsed" $
+        it "should return Left (ParseError Char Void)" $
+          let varContent = "123x"
+              integer = EnvInteger
+           in varContent `parseEnvAs` integer `shouldSatisfy` isLeft
+
+    context "given a bool" $ do
+      context "when the bool can be parsed" $
+        it "should return Right ()" $
+          let varContent = "true"
+              boolean = EnvBool
+           in varContent `parseEnvAs` boolean `shouldSatisfy` isRight
+
+      context "when the bool can't be parsed" $
+        it "should return False" $
+          let varContent = "truex"
+              boolean = EnvBool
+           in varContent `parseEnvAs` boolean `shouldSatisfy` isLeft
diff --git a/spec/Configuration/Dotenv/SchemeSpec.hs b/spec/Configuration/Dotenv/SchemeSpec.hs
new file mode 100644
--- /dev/null
+++ b/spec/Configuration/Dotenv/SchemeSpec.hs
@@ -0,0 +1,60 @@
+module Configuration.Dotenv.SchemeSpec (spec) where
+
+import Configuration.Dotenv.Scheme
+import Configuration.Dotenv.Scheme.Types
+
+import Test.Hspec
+
+spec :: Spec
+spec =
+  describe "checkConfig" $
+    context "when the envs have the correct type" $ do
+      context "when the envs in the dotenvs are defined in the scheme" $ do
+        context "when the required envs are defined" $
+          it "should succeed the type check" $
+            let schemeEnvs =
+                    [ Env "FOO" EnvBool True
+                    , Env "BAR" EnvInteger False
+                    ]
+                dotenvs = [("FOO","true"), ("BAR","123")]
+             in checkConfig dotenvs schemeEnvs `shouldReturn` ()
+
+        context "when the not required envs are missing" $
+          it "should succeed the type check" $
+            let schemeEnvs =
+                    [ Env "FOO" EnvBool True
+                    , Env "BAR" EnvInteger False
+                    ]
+                dotenvs = [("FOO","true")]
+             in checkConfig dotenvs schemeEnvs `shouldReturn` ()
+
+        context "when the required envs are missing" $
+          it "should fail before the type check" $
+            let schemeEnvs =
+                    [ Env "FOO" EnvBool True
+                    , Env "BAR" EnvInteger False
+                    ]
+                dotenvs = [("BAR","123")]
+                msg = "The following envs: FOO must be in the dotenvs"
+              in checkConfig dotenvs schemeEnvs `shouldThrow` errorCall msg
+
+      context "when there are missing dotenvs in the scheme" $
+        it "should fail before type checking" $
+          let schemeEnvs =
+                  [ Env "FOO" EnvBool True
+                  , Env "BAR" EnvInteger False
+                  ]
+              dotenvs = [("FOO","true"), ("BAR","123"), ("BAZ","text")]
+              msg = "The following envs: BAZ must be in your scheme.yml"
+           in checkConfig dotenvs schemeEnvs `shouldThrow` errorCall msg
+
+      context "when there are missing scheme envs in the dotenv vars" $
+        it "should fail before type checking" $
+          let schemeEnvs =
+                  [ Env "FOO" EnvBool True
+                  , Env "BAZ" EnvText True
+                  , Env "BAR" EnvInteger False
+                  ]
+              dotenvs = [("FOO","true"), ("BAR","123")]
+              msg = "The following envs: BAZ must be in the dotenvs"
+           in checkConfig dotenvs schemeEnvs `shouldThrow` errorCall msg
diff --git a/spec/Configuration/DotenvSpec.hs b/spec/Configuration/DotenvSpec.hs
--- a/spec/Configuration/DotenvSpec.hs
+++ b/spec/Configuration/DotenvSpec.hs
@@ -8,8 +8,8 @@
 import Test.Hspec
 
 import System.Process (readCreateProcess, shell)
-import System.Environment (lookupEnv)
-import Control.Monad (liftM)
+import System.Environment (lookupEnv, getEnv)
+import Control.Monad (liftM, void)
 import Data.Maybe (fromMaybe)
 #if !MIN_VERSION_base(4,8,0)
 import Data.Functor ((<$>))
@@ -58,21 +58,21 @@
     it "loads the configuration options to the environment from a file" $ do
       lookupEnv "DOTENV" `shouldReturn` Nothing
 
-      loadFile $ Config ["spec/fixtures/.dotenv"] [] False
+      void $ loadFile $ Config ["spec/fixtures/.dotenv"] [] False
 
       lookupEnv "DOTENV" `shouldReturn` Just "true"
 
     it "respects predefined settings when overload is false" $ do
       setEnv "DOTENV" "preset"
 
-      loadFile $ Config ["spec/fixtures/.dotenv"] [] False
+      void $ loadFile $ Config ["spec/fixtures/.dotenv"] [] False
 
       lookupEnv "DOTENV" `shouldReturn` Just "preset"
 
     it "overrides predefined settings when overload is true" $ do
       setEnv "DOTENV" "preset"
 
-      loadFile $ Config ["spec/fixtures/.dotenv"] [] True
+      void $ loadFile $ Config ["spec/fixtures/.dotenv"] [] True
 
       lookupEnv "DOTENV" `shouldReturn` Just "true"
 
@@ -81,12 +81,14 @@
 
       context "when the needed env vars are missing" $
         it "should fail with an error call" $
-          loadFile config `shouldThrow` anyErrorCall
+          void $ loadFile config `shouldThrow` anyErrorCall
 
       context "when the needed env vars are not missing" $
         it "should succeed when loading all of the needed env vars" $ do
           setEnv "ANOTHER_ENV" "hello"
-          loadFile config `shouldReturn` ()
+          me <- getEnv "USER"
+          home <- getEnv "HOME"
+          loadFile config `shouldReturn` [("DOTENV","true"),("UNICODE_TEST","Manab\237"),("ENVIRONMENT", home),("PREVIOUS","true"),("ME", me),("ANOTHER_ENV","")]
           lookupEnv "DOTENV" `shouldReturn` Just "true"
           lookupEnv "UNICODE_TEST" `shouldReturn` Just "Manabí"
           lookupEnv "ANOTHER_ENV" `shouldReturn` Just "hello"
@@ -121,7 +123,7 @@
   describe "onMissingFile" $ after_ (unsetEnv "DOTENV") $ do
     context "when target file is present" $
       it "loading works as usual" $ do
-        onMissingFile (loadFile $ Config ["spec/fixtures/.dotenv"] [] True) (return ())
+        void $ onMissingFile (loadFile $ Config ["spec/fixtures/.dotenv"] [] True) (return [])
         lookupEnv "DOTENV" `shouldReturn` Just "true"
 
     context "when target file is missing" $
diff --git a/spec/fixtures/.scheme.yml b/spec/fixtures/.scheme.yml
new file mode 100644
--- /dev/null
+++ b/spec/fixtures/.scheme.yml
@@ -0,0 +1,14 @@
+- name: DOTENV
+  type: bool
+  required: true
+- name: OTHERENV
+  type: bool
+  required: false
+- name: PORT
+  type: integer
+  required: true
+- name: TOKEN
+  type: integer
+- name: URL
+  type: text
+  required: true
diff --git a/src/Configuration/Dotenv.hs b/src/Configuration/Dotenv.hs
--- a/src/Configuration/Dotenv.hs
+++ b/src/Configuration/Dotenv.hs
@@ -52,7 +52,7 @@
 loadFile
   :: MonadIO m
   => Config
-  -> m ()
+  -> m [(String, String)]
 loadFile Config{..} = do
   environment <- liftIO getEnvironment
   readedVars <- concat `liftM` mapM parseFile configPath
@@ -68,7 +68,7 @@
               then readedVars `unionEnvs` neededVars
               else error $ "Missing env vars! Please, check (this/these) var(s) (is/are) set:" ++ concatMap ((++) " " . fst) neededVars
           else readedVars
-  mapM_ (applySetting configOverride) vars
+  mapM (applySetting configOverride) vars
 
 -- | Parses the given dotenv file and returns values /without/ adding them to
 -- the environment.
@@ -83,17 +83,16 @@
     Left e        -> error $ parseErrorPretty e
     Right options -> liftIO $ interpolateParsedVariables options
 
-applySetting :: MonadIO m => Bool -> (String, String) -> m ()
+applySetting :: MonadIO m => Bool -> (String, String) -> m (String, String)
 applySetting override (key, value) =
-  if override then
-    liftIO $ setEnv key value
-
-  else do
-    res <- liftIO $ lookupEnv key
+  if override
+    then liftIO (setEnv key value) >> return (key, value)
+    else do
+      res <- liftIO $ lookupEnv key
 
-    case res of
-      Nothing -> liftIO $ setEnv key value
-      Just _  -> return ()
+      case res of
+        Nothing -> liftIO $ setEnv key value >> return (key, value)
+        Just _  -> return (key, value)
 
 -- | The helper allows to avoid exceptions in the case of missing files and
 -- perform some action instead.
diff --git a/src/Configuration/Dotenv/Scheme.hs b/src/Configuration/Dotenv/Scheme.hs
new file mode 100644
--- /dev/null
+++ b/src/Configuration/Dotenv/Scheme.hs
@@ -0,0 +1,70 @@
+module Configuration.Dotenv.Scheme
+  ( checkConfig
+  , loadSafeFile
+  , runSchemaChecker
+  )
+  where
+
+import Control.Monad
+import Control.Monad.IO.Class (MonadIO(..))
+
+import Data.Yaml (decodeFileEither, prettyPrintParseException)
+import Text.Megaparsec
+import System.Directory (doesFileExist)
+
+import Configuration.Dotenv (loadFile)
+import Configuration.Dotenv.Types (Config(..))
+import Configuration.Dotenv.Scheme.Helpers
+import Configuration.Dotenv.Scheme.Parser
+import Configuration.Dotenv.Scheme.Types
+
+-- | @loadSafeFile@ parses the /.scheme.yml/ file and will perform the type checking
+-- of the environment variables in the /.env/ file.
+loadSafeFile
+  :: MonadIO m
+  => FilePath
+  -> Config
+  -> m [(String, String)]
+loadSafeFile schemaFile config = do
+  envs <- loadFile config
+  liftIO (readScheme schemaFile >>= checkConfig envs)
+  return envs
+
+readScheme :: FilePath -> IO [Env]
+readScheme schemeFile = do
+  eitherEnvConf <- decodeFileEither schemeFile
+  case eitherEnvConf of
+    Right envConfs -> return envConfs
+    Left errorYaml -> error (prettyPrintParseException errorYaml)
+
+checkConfig
+  :: [(String, String)]
+  -> [Env]
+  -> IO ()
+checkConfig envvars envsWithType =
+  let prettyParsedErrors = unlines . fmap parseErrorTextPretty
+      envsTypeAndValue   = joinEnvs envsWithType envvars
+      valuesAndTypes     = matchValueAndType envsTypeAndValue
+      dotenvsMissing     = filter required (missingDotenvs envsWithType envsTypeAndValue)
+      schemeEnvsMissing  = missingSchemeEnvs envvars envsTypeAndValue
+   in do
+     unless (null dotenvsMissing)
+       (error $ "The following envs: "
+                  ++ showMissingDotenvs dotenvsMissing
+                  ++ " must be in the dotenvs")
+     unless (null schemeEnvsMissing)
+       (error $ "The following envs: "
+                  ++ showMissingSchemeEnvs schemeEnvsMissing
+                  ++ " must be in your scheme.yml")
+     case parseEnvsWithScheme valuesAndTypes of
+        Left errors -> error (prettyParsedErrors errors)
+        _ -> return ()
+
+runSchemaChecker
+  :: FilePath
+  -> Config
+  -> IO ()
+runSchemaChecker schemeFile config = do
+  exists <- doesFileExist schemeFile
+  when exists
+     (void $ loadSafeFile schemeFile config)
diff --git a/src/Configuration/Dotenv/Scheme/Helpers.hs b/src/Configuration/Dotenv/Scheme/Helpers.hs
new file mode 100644
--- /dev/null
+++ b/src/Configuration/Dotenv/Scheme/Helpers.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE CPP             #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Configuration.Dotenv.Scheme.Helpers
+  ( joinEnvs
+  , matchValueAndType
+  , missingDotenvs
+  , missingSchemeEnvs
+  , sepWithCommas
+  , showMissingDotenvs
+  , showMissingSchemeEnvs
+  )
+  where
+
+#if !MIN_VERSION_base(4,8,0)
+import Data.Functor ((<$>))
+import Control.Applicative ((<*>))
+#endif
+import Data.List
+
+import Configuration.Dotenv.Scheme.Types
+
+matchValueAndType
+  :: [(Env, (String, String))]
+  -> [(String, EnvType)]
+matchValueAndType =
+  let getValueAndType (Env{..}, (_, value)) = (value, envType)
+   in map getValueAndType
+
+joinEnvs
+  :: [Env]
+  -> [(String, String)]
+  -> [(Env, (String, String))]
+joinEnvs =
+  let sameName (Env{..}, (name,_)) = envName == name
+   in joinBy sameName
+
+joinBy :: ((a,b) -> Bool) -> [a] -> [b] -> [(a,b)]
+joinBy p xs ys =
+  let cartesianProduct = (,) <$> xs <*> ys
+   in filter p cartesianProduct
+
+missingDotenvs
+  :: [Env]
+  -> [(Env, (String, String))]
+  -> [Env]
+missingDotenvs =
+  let sameName envOne envTwo = envName envOne == envName envTwo
+   in missingLeft sameName
+
+missingLeft :: (a -> a -> Bool) -> [a] -> [(a,b)] -> [a]
+missingLeft p xs xys =
+  let getAllLeft = map fst xys
+   in deleteFirstsBy p xs getAllLeft
+
+missingSchemeEnvs
+  :: [(String, String)]
+  -> [(Env, (String, String))]
+  -> [(String, String)]
+missingSchemeEnvs =
+  let sameName (nameOne,_) (nameTwo,_) = nameOne == nameTwo
+   in missingRight sameName
+
+missingRight :: (b -> b -> Bool) -> [b] -> [(a,b)] -> [b]
+missingRight p ys xys =
+  let getAllRight = map snd xys
+   in deleteFirstsBy p ys getAllRight
+
+sepWithCommas :: [String] -> String
+sepWithCommas = intercalate ", "
+
+showMissingDotenvs :: [Env] -> String
+showMissingDotenvs = sepWithCommas . map envName
+
+showMissingSchemeEnvs :: [(String, String)] -> String
+showMissingSchemeEnvs = sepWithCommas . map fst
diff --git a/src/Configuration/Dotenv/Scheme/Parser.hs b/src/Configuration/Dotenv/Scheme/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Configuration/Dotenv/Scheme/Parser.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Configuration.Dotenv.Scheme.Parser where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((*>), pure)
+import Data.Functor ((<$>))
+#endif
+
+import Data.Either
+import Data.Void
+import Text.Megaparsec
+import Text.Megaparsec.Char
+
+import Configuration.Dotenv.Scheme.Types
+
+parseEnvsWithScheme
+  :: [(String, EnvType)]
+  -> Either [ParseError Char Void] ()
+parseEnvsWithScheme valuesAndTypes =
+  let parsedEithers = parseEnvs <$> valuesAndTypes
+      parseEnvs (val, type') = val `parseEnvAs` type'
+    in if all isRight parsedEithers
+          then Right ()
+          else Left (lefts parsedEithers)
+
+parseEnvAs
+  :: String -- ^ Value of the env variable
+  -> EnvType -- ^ Type that the env variable should have
+  -> Either (ParseError Char Void) ()
+parseEnvAs envVal envTypeNeeded =
+  parse dispatch "" envVal
+    where
+      errorMsg = "Couldn't parse " ++ envVal ++ " as " ++ showType envTypeNeeded
+      evalParse parser = parser *> eof *> pure () <|> fail errorMsg
+      dispatch :: Parsec Void String ()
+      dispatch =
+        case envTypeNeeded of
+          EnvInteger -> evalParse (many digitChar)
+          EnvBool    -> evalParse (string "true" <|> string "false")
+          EnvText    -> pure ()
+
+showType :: EnvType -> String
+showType EnvInteger = "integer"
+showType EnvBool = "boolean"
+showType _ = "text"
diff --git a/src/Configuration/Dotenv/Scheme/Types.hs b/src/Configuration/Dotenv/Scheme/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Configuration/Dotenv/Scheme/Types.hs
@@ -0,0 +1,38 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Configuration.Dotenv.Scheme.Types where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<*>), pure)
+import Data.Functor ((<$>))
+#endif
+
+import Data.Yaml
+
+data EnvType =
+  EnvInteger
+    | EnvBool
+    | EnvText deriving (Show, Eq)
+
+instance FromJSON EnvType where
+  parseJSON (String "integer") = pure EnvInteger
+  parseJSON (String "bool") = pure EnvBool
+  parseJSON (String "text") = pure EnvText
+  parseJSON (String x) = fail ("Don't know how to parse that kind of type: " ++ show x)
+  parseJSON x = fail ("Not an object: " ++ show x)
+
+data Env =
+  Env
+    { envName  :: String
+    , envType  :: EnvType
+    , required :: Bool
+    } deriving (Show, Eq)
+
+instance FromJSON Env where
+  parseJSON (Object m) =
+    Env
+      <$> m .: "name"
+      <*> m .: "type"
+      <*> m .:? "required" .!= False
+  parseJSON x = fail ("Not an object: " ++ show x)
