diff --git a/Control/Monad/State/Puts.hs b/Control/Monad/State/Puts.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/State/Puts.hs
@@ -0,0 +1,11 @@
+module Control.Monad.State.Puts
+  (puts)
+  where
+
+import Control.Monad.State
+
+-- | Puts is just an opposite to gets.
+-- Compare `x <- gets field' with `puts setField newValue'.
+puts :: (MonadState s m) => (a -> s -> s) -> a -> m ()
+puts fn value = modify (fn value)
+
diff --git a/Data/Setters.hs b/Data/Setters.hs
new file mode 100644
--- /dev/null
+++ b/Data/Setters.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE TemplateHaskell #-}
+module Data.Setters
+  (declareSetters,
+   declareSetters'
+  )
+  where
+
+import Data.Char
+import Language.Haskell.TH
+
+-- | Declare setters for all fields of given `data' type.
+-- For example, for 
+--
+-- > data Record = Record {
+-- >       ...
+-- >       someField :: Integer,
+-- >       ... }
+--
+-- one will automatically get
+--
+-- > someField :: Record -> Integer.
+--
+-- After calling
+--
+-- > $(declareSetters ''Record)
+--
+-- one will get
+--
+-- > setSomeField :: Integer -> Record -> Record.
+declareSetters :: Name -> Q [Dec]
+declareSetters name = do
+  (TyConI (DataD _ _ _ cons _)) <- reify name
+  return $ concatMap (conSetters "") cons
+
+-- | Similar to 'declareSetters', but add data type name to all setters' names.
+-- For example, one will get `setRecordSomeField' instead of `setSomeField'.
+declareSetters' :: Name -> Q [Dec]
+declareSetters' name = do
+  (TyConI (DataD _ _ _ cons _)) <- reify name
+  return $ concatMap (conSetters $ nameBase name) cons
+
+conSetters :: String -> Con -> [Dec]
+conSetters prefix (RecC _ fields) = map (fieldSetter prefix) fields
+conSetters prefix _               = []
+
+capitalize :: String -> String
+capitalize [] = []
+capitalize (x:xs) = toUpper x: xs
+
+fieldSetter :: String -> (Name, Strict, Type) -> Dec
+fieldSetter prefix (name, _, _) =
+  let name'  = mkName $ "set" ++ capitalize prefix ++ (capitalize $ nameBase name)
+      record = mkName "record"
+      value  = mkName "value"
+      body   = RecUpdE (VarE record) [(name, VarE value)]
+      clause = Clause [VarP value, VarP record] (NormalB body) []
+  in  FunD name' [clause]
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2010, IlyaPortnov
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of IlyaPortnov nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Test.hs b/Test.hs
new file mode 100644
--- /dev/null
+++ b/Test.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+import Control.Monad
+import Control.Monad.Trans
+import Control.Monad.State
+
+import Control.Monad.State.Puts
+import Data.Setters
+
+data Record = Record {
+  count :: Int,
+  flag :: Bool }
+  deriving (Eq, Show)
+
+$(declareSetters ''Record)
+
+testState :: StateT Record IO ()
+testState = do
+  cnt <- gets count
+  puts setCount (cnt + 1)
+  puts setFlag (odd cnt)
+  liftIO $ print cnt
+
+main = do
+  runStateT (replicateM 10 testState) (Record 0 False)
+  return ()
diff --git a/setters.cabal b/setters.cabal
new file mode 100644
--- /dev/null
+++ b/setters.cabal
@@ -0,0 +1,45 @@
+Name:                setters
+
+Version:             0.1
+
+Synopsis:            Small (TH) library to declare setters for typical `record' data type fields.
+
+-- A longer description of the package.
+Description:         Haskell declares a getter for each `record' style data type field.
+                     This library will help you declare setters (`setFieldName' function for `fieldName' field).
+
+License:             BSD3
+
+License-file:        LICENSE
+
+Author:              IlyaPortnov
+
+Maintainer:          portnov84@rambler.ru
+
+-- A copyright notice.
+-- Copyright:           
+
+Category:            Data
+
+Build-type:          Simple
+
+-- Extra files to be distributed with the package, such as examples or
+-- a README.
+Extra-source-files:  Test.hs
+
+-- Constraint on the version of Cabal needed to build this package.
+Cabal-version:       >=1.6
+
+
+Library
+  -- Modules exported by the library.
+  Exposed-modules:     Data.Setters, Control.Monad.State.Puts
+  
+  -- Packages needed in order to build this package.
+  Build-depends:       base >= 3 && <= 5, mtl, template-haskell
+  
+  -- Modules not exported by this package.
+  -- Other-modules:       
+  
+  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.
+  -- Build-tools:         
