diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) Henning Thielemann
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. 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.
+3. Neither the name of the University nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#! /usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/data-ref.cabal b/data-ref.cabal
new file mode 100644
--- /dev/null
+++ b/data-ref.cabal
@@ -0,0 +1,41 @@
+Name:             data-ref
+Version:          0.0
+License:          BSD3
+License-File:     LICENSE
+Author:           Henning Thielemann <haskell@henning-thielemann.de>
+Maintainer:       Henning Thielemann <haskell@henning-thielemann.de>
+Category:         Data
+Homepage:         http://www.haskell.org/haskellwiki/Mutable_variable
+Synopsis:         Unify STRef and IORef in plain Haskell 98
+Description:
+  This package provides a unique interface to both STRef and IORef.
+  The advantage is that it is plain Haskell 98,
+  the disadvantage is that we cannot use STRef and IORef as they are.
+  .
+  Our approach works with Haskell 98 single parameter type classes
+  because we use an explicit dictionary,
+  and we do not pass the references around but their accessors.
+  .
+  Similar packages: @reference@, @ref-mtl@, @ref-fd@, @ref-tf@.
+Tested-With:       GHC==7.4.2
+Cabal-Version:     >=1.6
+Build-Type:        Simple
+Source-Repository head
+  type:     darcs
+  location: http://code.haskell.org/~thielema/data-ref/
+
+Source-Repository this
+  type:     darcs
+  location: http://code.haskell.org/~thielema/data-ref/
+  tag:      0.0
+
+Library
+  Build-Depends:
+    transformers >=0.2 && <0.4,
+    stm >=2.2 && <2.4,
+    base >=2 && <5
+
+  GHC-Options:      -Wall
+  Hs-Source-Dirs:   src
+  Exposed-Modules:
+    Data.Ref
diff --git a/src/Data/Ref.hs b/src/Data/Ref.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Ref.hs
@@ -0,0 +1,84 @@
+{-
+Following an idea by Dominique Devriese:
+<http://www.haskell.org/pipermail/libraries/2013-June/020185.html>
+-}
+module Data.Ref where
+
+import Data.IORef (newIORef, readIORef, writeIORef, )
+import Data.STRef (newSTRef, readSTRef, writeSTRef, )
+import Control.Concurrent.STM.TVar (newTVar, readTVar, writeTVar, )
+import Control.Concurrent.STM (STM, )
+import Control.Monad.ST (ST)
+import Control.Monad (liftM)
+
+import qualified Control.Monad.Trans.Class as MT
+import qualified Control.Monad.IO.Class as MIO
+
+import qualified Control.Monad.Trans.RWS.Lazy as MRWSL
+import qualified Control.Monad.Trans.RWS.Strict as MRWSS
+import qualified Control.Monad.Trans.State.Lazy as MSL
+import qualified Control.Monad.Trans.State.Strict as MSS
+import qualified Control.Monad.Trans.Writer.Lazy as MWL
+import qualified Control.Monad.Trans.Writer.Strict as MWS
+import qualified Control.Monad.Trans.Cont as MC
+import qualified Control.Monad.Trans.Error as ME
+import qualified Control.Monad.Trans.Maybe as MM
+import qualified Control.Monad.Trans.Reader as MR
+import qualified Control.Monad.Trans.Identity as MI
+import Data.Monoid (Monoid)
+
+import Prelude hiding (read)
+
+
+data T m a = Cons { write :: a -> m (), read :: m a }
+
+modify :: C m => T m a -> (a -> a) -> m ()
+modify ref f = write ref . f =<< read ref
+
+newCons :: C m =>
+   (a -> m ref) -> (ref -> a -> m ()) -> (ref -> m a) ->
+   a -> m (T m a)
+newCons nw wr rd = liftM (\r -> Cons (wr r) (rd r)) . nw
+
+
+class Monad m => C m where
+   new :: a -> m (T m a)
+
+instance C IO where
+   new = newCons newIORef writeIORef readIORef
+
+instance C (ST s) where
+   new = newCons newSTRef writeSTRef readSTRef
+
+instance C STM where
+   new = newCons newTVar writeTVar readTVar
+
+
+{-
+mapMonad :: (Monad m, Monad n) => (forall b. m b -> n b) -> T m a -> T n a
+mapMonad lft (Cons wr rd) = Cons (lft . wr) (lft rd)
+-}
+
+lift :: (Monad m, MT.MonadTrans t) => T m a -> T (t m) a
+lift (Cons wr rd) = Cons (MT.lift .wr) (MT.lift rd)
+
+liftIO :: (MIO.MonadIO m) => T IO a -> T m a
+liftIO (Cons wr rd) = Cons (MIO.liftIO .wr) (MIO.liftIO rd)
+
+newLifted :: (C m, MT.MonadTrans t) => a -> t m (T (t m) a)
+newLifted = MT.lift . liftM lift . new
+
+
+instance C m => C (MI.IdentityT m) where new = newLifted
+
+instance C m => C (MM.MaybeT m) where new = newLifted
+instance (ME.Error e, C m) => C (ME.ErrorT e m) where new = newLifted
+
+instance C m => C (MC.ContT r m) where new = newLifted
+instance C m => C (MR.ReaderT r m) where new = newLifted
+instance C m => C (MSS.StateT s m) where new = newLifted
+instance C m => C (MSL.StateT s m) where new = newLifted
+instance (Monoid w, C m) => C (MWS.WriterT w m) where new = newLifted
+instance (Monoid w, C m) => C (MWL.WriterT w m) where new = newLifted
+instance (Monoid w, C m) => C (MRWSS.RWST r w s m) where new = newLifted
+instance (Monoid w, C m) => C (MRWSL.RWST r w s m) where new = newLifted
