diff --git a/spata.cabal b/spata.cabal
--- a/spata.cabal
+++ b/spata.cabal
@@ -1,19 +1,19 @@
 Name:                 spata
-Version:              2009.9.18.1
+Version:              2010.10.10
 Build-type:           Simple
-Synopsis:             bruteforce form validation
+Synopsis:             brainless form validation
 Description:
         
-    who needs a brain when it can be solved with fists
+    tiny validation library
 
 License:              BSD3
 License-file:         LICENSE
-Author:               Wang, Jinjing
-Maintainer:           Wang, Jinjing <nfjinjing@gmail.com>
+Author:               Jinjing Wang
+Maintainer:           Jinjing Wang <nfjinjing@gmail.com>
 Build-Depends:        base
 Cabal-version:        >= 1.2
 category:             Web
-homepage:             http://github.com/nfjinjing/spata/tree/master
+homepage:             http://github.com/nfjinjing/spata
 data-files:           readme.md, changelog.md, known-issues.md, Nemesis, src/test.hs
 
 library
diff --git a/src/Network/Spata/DSL.hs b/src/Network/Spata/DSL.hs
--- a/src/Network/Spata/DSL.hs
+++ b/src/Network/Spata/DSL.hs
@@ -1,41 +1,89 @@
+{-# LANGUAGE PackageImports #-}
+
 module Network.Spata.DSL where
 
 import Data.DList (singleton, toList, fromList)
-import Control.Monad.Writer
+import "mtl" Control.Monad.Writer
+import "mtl" Control.Monad.Error ()
 import MPS.Env
 import Prelude ()
 import Data.Maybe
 import Network.Spata.Type
-import Control.Monad.Error
-import MPS (empty)
+import MPS (empty, match)
 
 guard :: Assoc -> Guardians -> Either String Assoc
-guard xs m = execWriter m .toList .inject (Right xs) (>>=)
+guard inputs m = execWriter m .toList .inject (Right inputs) (>>=)
 
 validate :: Guard -> [String]-> Guardians
-validate f xs = 
-  tell - fromList - xs.map f
+validate f inputs = 
+  tell - fromList - inputs.map f
 
 train :: Task -> Guardians
 train f = tell - singleton f
 
 inclusion_of :: Guard
-inclusion_of = p (const True) ""
+inclusion_of = predicate (const True) ""
 
 presence_of :: Guard
-presence_of = p (empty > not) "should not be empty"
+presence_of = predicate (empty > not) "should not be empty"
 
 length_of :: (Integer -> Bool) -> Guard
-length_of f = p (length > from_i > f) "should satisfy length properties"
+length_of f = predicate (length > from_i > f) "should satisfy length properties"
 
-p = predicate
+int_of :: Guard
+int_of = predicate (match "^\\d+$" > isJust) "should be integer"
 
-predicate, p :: (String -> Bool) -> String -> Guard
-predicate f s x xs =
-  case xs.lookup x of
-    Nothing -> Left - x ++ " should exist"
+
+predicate :: (String -> Bool) -> String -> Guard
+predicate f s x inputs =
+  case inputs.lookup x of
+    Nothing -> Left - x + " should exist"
     Just y ->
       if f y
-        then Right xs
-        else Left - x ++ " " ++ s
+        then Right inputs
+        else Left - x + " " + s
+
+
+-- monad, mostly used in IO
+
+validate_m :: (Monad m) => GuardM m -> [String] -> GuardiansM m
+validate_m f inputs =
+  tell - fromList - inputs.map f
+
+predicate_m :: (Monad m) => (String -> m Bool) -> String -> GuardM m
+predicate_m f s x inputs =
+  case inputs.lookup x of
+    Nothing -> return - Left - x + " should exist"
+    Just y -> do
+      r <- f y
+      if r
+        then return - Right inputs
+        else return - Left - x + " " + s
+
+guard_m :: (Monad m) => Assoc -> GuardiansM m -> m (Either String Assoc)
+guard_m inputs m = do
+  let tasks = execWriter m .toList
+  
+  lazy_eval tasks - Right inputs
+  where
+    lazy_eval [] last_validation_result = return - last_validation_result
+    lazy_eval _ (Left r) = return - Left r
+    lazy_eval (p':ps) (Right xs) = do
+      validation_result <- p' xs
+      lazy_eval ps validation_result
+  
         
+        
+        
+-- alias
+p :: (String -> Bool) -> String -> Guard
+p = predicate
+
+validateM :: (Monad m) => GuardM m -> [String] -> GuardiansM m
+validateM = validate_m
+
+predicateM :: (Monad m) => (String -> m Bool) -> String -> GuardM m
+predicateM = predicate_m
+
+guardM :: (Monad m) => Assoc -> GuardiansM m -> m (Either String Assoc)
+guardM = guard_m
diff --git a/src/Network/Spata/Type.hs b/src/Network/Spata/Type.hs
--- a/src/Network/Spata/Type.hs
+++ b/src/Network/Spata/Type.hs
@@ -1,13 +1,20 @@
+{-# LANGUAGE PackageImports #-}
+
 module Network.Spata.Type where
 
 import Data.DList (DList)
-import Control.Monad.Writer
+import "mtl" Control.Monad.Writer
 
 type Assoc = [(String, String)]
 type Guard = String -> Assoc -> Either String Assoc
-type Guards = [String] -> Assoc -> Either String Assoc
+
+-- type Guards = [String] -> Assoc -> Either String Assoc
 type Task = Assoc -> Either String Assoc
 
 type GuardiansT a = Writer (DList Task) a
 type Guardians = GuardiansT ()
 
+type GuardM m = String -> Assoc -> m (Either String Assoc)
+type TaskM m = Assoc -> m (Either String Assoc)
+type GuardiansTM a m = Writer (DList (TaskM m)) a
+type GuardiansM m = GuardiansTM () m
