diff --git a/salak.cabal b/salak.cabal
--- a/salak.cabal
+++ b/salak.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.12
 name: salak
-version: 0.3.3
+version: 0.3.3.1
 license: MIT
 license-file: LICENSE
 copyright: 2019 Daniel YU
@@ -26,12 +26,13 @@
         Salak.Internal.Prop
         Salak.Internal.Writable
     default-language: Haskell2010
-    default-extensions: RecordWildCards
+    default-extensions: RecordWildCards TupleSections
     ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures
     build-depends:
         attoparsec >=0.13.2.2 && <0.14,
         base >=4.10 && <5,
         bytestring >=0.10.8.2 && <0.11,
+        containers >=0.6.0.1 && <0.7,
         data-default >=0.7.1.1 && <0.8,
         directory >=1.3.3.0 && <1.4,
         exceptions >=0.10.2 && <0.11,
@@ -61,13 +62,14 @@
         Salak.Trie
         Paths_salak
     default-language: Haskell2010
-    default-extensions: RecordWildCards
+    default-extensions: RecordWildCards TupleSections
     ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures
     build-depends:
         QuickCheck >=2.13.2 && <2.14,
         attoparsec >=0.13.2.2 && <0.14,
         base >=4.10 && <5,
         bytestring >=0.10.8.2 && <0.11,
+        containers >=0.6.0.1 && <0.7,
         data-default >=0.7.1.1 && <0.8,
         directory >=1.3.3.0 && <1.4,
         exceptions >=0.10.2 && <0.11,
diff --git a/src/Salak/Internal/Key.hs b/src/Salak/Internal/Key.hs
--- a/src/Salak/Internal/Key.hs
+++ b/src/Salak/Internal/Key.hs
@@ -6,6 +6,7 @@
   , simpleKeys
   , ToKeys(..)
   , isNum
+  , isStr
   ) where
 
 import           Control.Applicative  ((<|>))
diff --git a/src/Salak/Internal/Prop.hs b/src/Salak/Internal/Prop.hs
--- a/src/Salak/Internal/Prop.hs
+++ b/src/Salak/Internal/Prop.hs
@@ -23,9 +23,11 @@
 import qualified Data.ByteString.Lazy    as BL
 import           Data.Default
 import           Data.Fixed
+import           Data.Hashable           (Hashable)
 import qualified Data.HashMap.Strict     as HM
 import           Data.Int
 import           Data.List               (sortBy)
+import qualified Data.Map.Strict         as M
 import           Data.Maybe
 import           Data.Menshen
 import           Data.Scientific
@@ -174,6 +176,20 @@
       go s vs (k,t) = (:vs) <$> runProp s { pref = pref s ++ [k], source = t} fromProp
       g2 (a,_) (b,_) = compare b a
 
+instance {-# OVERLAPPABLE #-} (IsString s, FromProp m a) => FromProp m [(s, a)] where
+  fromProp = do
+    sp@SourcePack{..} <- askSalak
+    foldM (go sp) [] $ sortBy g2 $ filter (isStr.fst) $ HM.toList $ TR.getMap source
+    where
+      go s vs (k,t) = (:vs) . (fromString $ show $ Keys [k],) <$> runProp s { pref = pref s ++ [k], source = t} fromProp
+      g2 (a,_) (b,_) = compare b a
+
+instance (Eq s, Hashable s, IsString s, FromProp m a) => FromProp m (HM.HashMap s a) where
+  fromProp = HM.fromList <$> fromProp
+
+instance (Eq s, Ord s, IsString s, FromProp m a) => FromProp m (M.Map s a) where
+  fromProp = M.fromList <$> fromProp
+
 -- | Supports for parsing `IO` value.
 instance {-# OVERLAPPABLE #-} (MonadIO m, MonadIO n, FromProp (Either SomeException) a, FromProp m a) => FromProp m (n a) where
   fromProp = do
@@ -287,6 +303,7 @@
   where
     go f (VT t) = f t
     go _ x      = Left $ fst (typeOfV x) ++ " cannot convert to enum"
+
 
 class Monad m => GFromProp m f where
   gFromProp :: Prop m (f a)
diff --git a/src/Salak/Internal/Writable.hs b/src/Salak/Internal/Writable.hs
--- a/src/Salak/Internal/Writable.hs
+++ b/src/Salak/Internal/Writable.hs
@@ -9,10 +9,10 @@
 import           Control.Concurrent.MVar
 import           Control.Monad
 
--- | Writable data structure. `Writable` is designed for working with `IO` value pased by salak. 
--- It provide a way to override `IO` value provided by salak, can be used in the application which need to change 
+-- | Writable data structure. `Writable` is designed for working with `IO` value pased by salak.
+-- It provide a way to override `IO` value provided by salak, can be used in the application which need to change
 -- values of some configurations by overriding it directly. For example, logger function can use a log level property
--- to control which level of logs should be printed. By using `Writeable` value, we can change the property 
+-- to control which level of logs should be printed. By using `Writeable` value, we can change the property
 -- directly.
 data Writable a = Writable
   { valRef :: IO a
