If you want to adorn the ugly default help message, augment the fields with descriptions:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
import Env
import Env.Generic
data Hello = Hello
{ name :: String ? "Whom shoud I greet?"
, count :: Int ? "How many times to greet them?"
, quiet :: Bool ? "Should I be quiet instead?"
} deriving (Show, Eq, Generic)
instance Record Error Hello
main :: IO ()
main = do
hello <- Env.parse (header "envparse example") record
print (hello :: Hello)
% runhaskell -isrc example/Generic1.hs
envparse example
Available environment variables:
COUNT How many times to greet them?
NAME Whom shoud I greet?
QUIET Should I be quiet instead?
Parsing errors:
COUNT is unset
NAME is unset
Note that this has an effect of wrapping the values in the Help constructor:
% NAME=bob COUNT=3 QUIET=YES runhaskell -isrc example/Generic1.hs
Hello {name = Help {unHelp = "bob"}, count = Help {unHelp = 3}, quiet = Help {unHelp = True}}
Given a Record e a instance, a value of the type a can be parsed from the environment.
If the parsing fails, a value of an error type e is returned.
The record method has a default implementation for any type that has a Generic instance. If you
need to choose a concrete type for e, the default error type Error is a good candidate. Otherwise,
the features you'll use in your parsers will naturally guide GHC to compute the set of required
constraints on e.
Given a Field e a instance, a value of the type a can be parsed from an environment variable.
If the parsing fails, a value of an error type e is returned.
The field method has a default implementation for any type that has a Read instance. If you
need to choose a concrete type for e, the default error type Error is a good candidate. Otherwise,
the features you'll use in your parsers will naturally guide GHC to compute the set of required
constraints on e.
The annotated instances do not use the default implementation.
If you annotate a record field with a Symbol literal (that is, a statically known type level string)
the derivation machinery will use the literal in the help message.
Please remember that the values of the annotated fields are wrapped in the Help constructor.