Package: Configurator
Minimum usable: configurator
There are many great Haskell libraries. But usually it will take equally great amount of effort for people to get familiar with them.
Worstly, it seems like some examples were designed to bring more obstracle deliberately.Packagesection follows theminimum usableprinciple. Examples of this section is clear enough for reminding myself in future. Hopefully, it will also offer some help to others. Issue in
online resouces:
Notes
- Config file
DemoOneInfo.cfgin dirctiondata.datais in the same level ofsrc.
DemoOneInfo
{
stringField = "This is demo ONE"
intField = 1
floatField = 1.3
homoListNum = [10,20,30,40,50]
homoListString = ["wuhao_1","emmettng_1"]
homoListBool = [true,false,false,false]
heteList = [1, "string", false]
}
- Simple data types
{-# LANGUAGE OverloadedStrings #-}
import Data.Configurator
import Data.Configurator.Types ## Value type
stringField :: IO String
stringField = do
cfg <- load [Required "data/configDemoOne.cfg"]
require cfg "DemoOneInfo.stringField" :: IO String
intField :: IO Int intField = do
cfg <- load [Required "data/configDemoOne.cfg"]
require cfg "DemoOneInfo.intField" :: IO Int
floatField :: IO Float
floatField = do
cfg <- load [Required "data/configDemoOne.cfg"]
require cfg "DemoOneInfo.floatField" :: IO Float
heteListField :: IO [Value]
heteListField = do
cfg <- load [Required "data/configDemoOne.cfg"]
require cfg "DemoOneInfo.heteList" :: IO [Value]
Output:
Prelude Packages.Configurator> stringField
"This is demo ONE"
Prelude Packages.Configurator> :info stringField
stringField :: IO String
Prelude Packages.Configurator> intField
1
Prelude Packages.Configurator> :info intField
intField :: IO Int
Prelude Packages.Configurator> floatField
1.3
Prelude Packages.Configurator> :info floatField
floatField :: IO Float
- Homogeneous List
homoIntListField :: IO [Int]
homoIntListField = do
fg <- load [Required "data/configDemoOne.cfg"]
equire cfg "DemoOneInfo.homoListNum" :: IO [Int]
homoStringListField :: IO [String]
homoStringListField = do
cfg <- load [Required "data/configDemoOne.cfg"]
require cfg "DemoOneInfo.homoListString" :: IO [String]
homoBoolListField :: IO [Bool]
homoBoolListField = do
cfg <- load [Required "data/configDemoOne.cfg"]
require cfg "DemoOneInfo.homoListBool" :: IO [Bool]
Output:
Prelude Packages.Configurator> homo
homoBoolListField homoIntListField homoStringListField
Prelude Packages.Configurator> homoBoolListField
[True,False,False,False]
Prelude Packages.Configurator> :info homoBoolListField
homoBoolListField :: IO [Bool]
Prelude Packages.Configurator> homoIntListField
[10,20,30,40,50]
Prelude Packages.Configurator> :info homoIntListField
homoIntListField :: IO [Int]
Prelude Packages.Configurator> homoStringListField
["wuhao_1","emmettng_1"]
Prelude Packages.Configurator> :info homoStringListField
homoStringListField :: IO [String]
- Heterogeneous
heteValueList :: IO [Value]
heteValueList = do
cfg <- load [Required "data/configDemoOne.cfg"]
require cfg "DemoOneInfo.heteList" :: IO [Value]
heteListField :: IO Value
heteListField = do
cfg <- load [Required "data/configDemoOne.cfg"]
require cfg "DemoOneInfo.heteList" :: IO Value
Value is the internal data type being used to bridge desire type and input in .cfg file. The example above usually indicate the use of customer data type rather than a list of Value.
Prelude Packages.Configurator Data.Configurator.Types> heteValueList
[Number (1 % 1),String "string",Bool False]
Prelude Packages.Configurator Data.Configurator.Types> :info heteValueList
heteValueList :: IO [Value]
Prelude Packages.Configurator Data.Configurator.Types> heteListField
List [Number (1 % 1),String "string",Bool False]
Prelude Packages.Configurator Data.Configurator.Types> :info heteListField
heteListField :: IO Value
- Nested section
nestDemo :: IO String
nestDemo = do
cfg <- load [Required "data/configDemo2.cfg"]
require cfg "Demo2Info.demo2_nest.nest-name" :: IO String
Output:
*Main Packages.Configurator> nestDemo
"dorothy"
*Main Packages.Configurator> :info nestDemo
nestDemo :: IO String
- Import other config files
demo filedata/configDemoThree.cfg
DemoThreeInfo
{
stringField = "This is Demo 3"
numberField = 3
floatField = 3.3
homoListNum = [1000,2000,3000,4000,5000]
homoListString = ["wuhao_3","emmettng_3"]
homoListBool = [true,true,true,false]
heteList = [3, "3string", true]
import "configDemoOne.cfg"
import "configDemo2.cfg"
}
importDemo :: IO String
importDemo = do
cfg <- load [Required "data/configDemoThree.cfg"]
require cfg "DemoThreeInfo.Demo2Info.demo2_nest.nest-name" :: IO String
Prelude Packages.Configurator> importDemo
"dorothy"
Prelude Packages.Configurator> :info importDemo
importDemo :: IO String
Note
configDemoThree.cfgis in the same directory withconfigDemoOne.cfganconfigDemo2.cfg. So just import the file name is ok!- The domain name of imported config are all being nested in the domain name
DemoThreeInfo.
- Customize Data type
demo file
data/ConfigDemoCustomize.cfg
DemoCustomizeInfo
{
stringField = "This is Demo 3"
numberField = 3
floatField = 3.3
homoListNum = [1000,2000,3000,4000,5000]
homoListString = ["wuhao_3","emmettng_3"]
homoListBool = [true,true,true,false]
heteList = [3, "3string", true]
custDemo = ["wh", 25, true,100]
}
-- | customize data type
--
--
data DemoFour = DemoFour
{ sName :: String
, iAge :: Int
, bAdult :: Bool
, fWeight :: Float
} deriving (Show)
instance Configured DemoFour where
convert :: Value -> Maybe DemoFour
convert (List [sV, nV, bV, fV]) = do
s <- convert sV :: Maybe String
n <- convert nV :: Maybe Int
b <- convert bV :: Maybe Bool
f <- convert fV :: Maybe Float
return $ DemoFour s n b f
convert _ = Nothing
customizeDemo :: IO DemoFour
customizeDemo = do
cfg <- load [Required "data/configDemoCustomize.cfg"]
require cfg "DemoCustomizeInfo.custDemo" :: IO DemoFour
Output:
*Main Packages.Configurator Data.Configurator Data.Configurator.Types Data.Maybe> :info customizeDemo
customizeDemo :: IO DemoFour
*Main Packages.Configurator Data.Configurator Data.Configurator.Types Data.Maybe> customizeDemo
DemoFour {sName = "wh", iAge = 25, bAdult = True, fWeight = 100.0}
*Main Packages.Configurator Data.Configurator Data.Configurator.Types Data.Maybe> :t sName <$> customizeDemo
sName <$> customizeDemo :: IO String
*Main Packages.Configurator Data.Configurator Data.Configurator.Types Data.Maybe> :t iAge <$> customizeDemo
iAge <$> customizeDemo :: IO Int
*Main Packages.Configurator Data.Configurator Data.Configurator.Types Data.Maybe> :t bAdult <$> customizeDemo
bAdult <$> customizeDemo :: IO Bool
*Main Packages.Configurator Data.Configurator Data.Configurator.Types Data.Maybe> :t fWeight <$> customizeDemo
fWeight <$> customizeDemo :: IO Float
-
Hot reloading
TODO