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.2.5
+version: 0.2.6
 license: BSD3
 license-file: LICENSE
 copyright: (c) 2018 Daniel YU
@@ -34,6 +34,7 @@
         data-default <0.8,
         directory <1.4,
         filepath <1.5,
+        menshen <0.1,
         mtl <2.3,
         pqueue <1.5,
         scientific <0.4,
@@ -58,7 +59,7 @@
     default-language: Haskell2010
     ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures
     build-depends:
-        QuickCheck <2.13,
+        QuickCheck <2.14,
         aeson <1.5,
         attoparsec <0.14,
         base >=4.7 && <5,
@@ -67,6 +68,7 @@
         directory <1.4,
         filepath <1.5,
         hspec ==2.*,
+        menshen <0.1,
         mtl <2.3,
         pqueue <1.5,
         scientific <0.4,
diff --git a/src/Salak.hs b/src/Salak.hs
--- a/src/Salak.hs
+++ b/src/Salak.hs
@@ -36,6 +36,7 @@
   , FromProp(..)
   , FromEnumProp(..)
   , (.?=)
+  , (.?:)
   -- * SourcePack
   , SourcePack
   , SourcePackT
@@ -140,7 +141,7 @@
 
 -- | Fetch dynamic properties from `SourcePack`, or throw fail
 requireD
-  :: (MonadIO m, HasSourcePack m, FromProp a)
+  :: (MonadIO m, FromProp a)
   => Text -- ^ Properties key
   -> ReloadableSourcePackT m (IO a)
 requireD k = do
@@ -151,7 +152,7 @@
 
 -- | Try fetch dynamic properties from `SourcePack`
 fetchD
-  :: (MonadIO m, HasSourcePack m, FromProp a)
+  :: (MonadIO m, FromProp a)
   => Text -- ^ Properties key
   -> ReloadableSourcePackT m (Either String (IO a))
 fetchD = search'
@@ -164,6 +165,11 @@
 infixl 5 .?=
 (.?=) :: Alternative f => f a -> a -> f a
 (.?=) a b = a <|> pure b
+
+-- | Default value.
+infixl 5 .?:
+(.?:) :: (Alternative f, Default b) => f a -> (b -> a) -> f a
+(.?:) fa b = fa .?= b def
 
 -- $use
 --
diff --git a/src/Salak/Prop.hs b/src/Salak/Prop.hs
--- a/src/Salak/Prop.hs
+++ b/src/Salak/Prop.hs
@@ -1,18 +1,21 @@
-{-# LANGUAGE DefaultSignatures    #-}
-{-# LANGUAGE DeriveFunctor        #-}
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE OverloadedStrings    #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeOperators        #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE DefaultSignatures          #-}
+{-# LANGUAGE DeriveFunctor              #-}
+{-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE ScopedTypeVariables        #-}
+{-# LANGUAGE TypeOperators              #-}
+{-# LANGUAGE TypeSynonymInstances       #-}
+{-# LANGUAGE UndecidableInstances       #-}
 module Salak.Prop where
 
 import           Control.Applicative
 import           Control.Monad.Reader
 import           Data.Int
 import qualified Data.IntMap.Strict   as MI
+import           Data.Menshen
 import qualified Data.PQueue.Min      as Q
 import           Data.Scientific
 import           Data.Text            (Text)
@@ -50,8 +53,20 @@
   (N s  ) >>= _ = N s
   (F s e) >>= _ = F s e
 
-type Prop a = ReaderT SourcePack PResult a
+newtype PropT m a = Prop { unProp :: ReaderT SourcePack m a }
+  deriving (Functor, Applicative, Monad, MonadTrans, Alternative)
 
+type Prop = PropT PResult
+
+runProp sp a = runReaderT (unProp a) sp
+
+instance MonadReader SourcePack Prop where
+  ask = Prop ask
+  local f (Prop a) = Prop (local f a)
+
+instance HasValid Prop where
+  invalid = err . toI18n
+
 instance FromProp a => IsString (Prop a) where
   fromString = readSelect . T.pack
 
@@ -98,7 +113,7 @@
 instance FromProp a => FromProp (Maybe a) where
   fromProp = do
     sp <- ask
-    lift $ case runReaderT (fromProp :: Prop a) sp of
+    lift $ case runProp sp (fromProp :: Prop a) of
       O s a -> O s $ Just a
       N s   -> O s Nothing
       F s e -> F s e
@@ -109,7 +124,7 @@
     foldM (go ss i it) [] $ MI.toList is
     where
       go xx x xt as (ix,s) = do
-        a <- lift $ runReaderT fromProp (SourcePack (SNum ix:xx) x s xt)
+        a <- lift $ runProp (SourcePack (SNum ix:xx) x s xt) fromProp
         return (a:as)
 
 instance {-# OVERLAPPABLE #-} FromEnumProp a => FromProp a where
@@ -144,7 +159,7 @@
   Right s -> local (\sp -> foldl select sp s) fromProp
 
 search :: FromProp a => Text -> SourcePack -> Either String a
-search key sp = case runReaderT (readSelect key) sp of
+search key sp = case runProp sp (readSelect key) of
   O _ x -> Right x
   N s   -> Left $ "key " ++ toKey s ++ " not found"
   F s e -> Left $ "key " ++ toKey s ++ " : " ++ e
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -16,7 +16,6 @@
 import           Test.Hspec
 import           Test.QuickCheck
 
-
 main = hspec spec
 
 spec :: Spec
@@ -95,7 +94,6 @@
         [ ("name", "Daniel")
         , ("age", "18")
         , ("male", "yes")
-        -- , ("det.hello", "world")
         ]
       e `shouldBe` []
       let a = search "" sp :: Either String Conf
