diff --git a/lgtk.cabal b/lgtk.cabal
--- a/lgtk.cabal
+++ b/lgtk.cabal
@@ -1,9 +1,9 @@
 name:               lgtk
-version:            0.3.2
+version:            0.4
 category:           GUI
-synopsis:           lens-based GUI with Gtk backend
+synopsis:           lens-based API for Gtk
 description:
-    The main interface of LGtk is "GUI.MLens.Gtk".
+    The main interface module of LGtk is "GUI.MLens.Gtk".
     .
     See also <http://people.inf.elte.hu/divip/LGtk/index.html>
 stability:          experimental
@@ -30,16 +30,8 @@
 
                   , gtk
   exposed-modules:
-                    Data.MLens
-                    Data.MLens.Ref
-
-                    Control.MLens.NewRef
-                    Control.MLens.NewRef.Unsafe
-                    Control.MLens.ExtRef
-                    Control.MLens.ExtRef.Test
-                    Control.MLens.ExtRef.Pure
-                    Control.MLens.ExtRef.Pure.Test
                     Control.MLens
+                    Control.MLens.Unsafe
 
                     GUI.MLens.Gtk
                     GUI.MLens.Gtk.ADTEditor
@@ -48,6 +40,15 @@
                     GUI.MLens.Gtk.Demos.IntListEditor
                     GUI.MLens.Gtk.Demos.TEditor
   other-modules:
+                    Data.MLens
+                    Data.MLens.Ref
+
+                    Control.MLens.NewRef
+                    Control.MLens.NewRef.Unsafe
+                    Control.MLens.ExtRef
+                    Control.MLens.ExtRef.Pure
+                    Control.MLens.ExtRef.Test
+
                     GUI.MLens.Gtk.IO
                     GUI.MLens.Gtk.Interface
   ghc-options: 
diff --git a/main/Main.hs b/main/Main.hs
--- a/main/Main.hs
+++ b/main/Main.hs
@@ -1,7 +1,7 @@
 import Control.Monad
 import Control.Monad.Trans
 
-import Data.MLens.Ref (fileRef)
+import Control.MLens.Unsafe (fileRef)
 import GUI.MLens.Gtk
 
 import GUI.MLens.Gtk.Demos.Tri
diff --git a/src/Control/MLens.hs b/src/Control/MLens.hs
--- a/src/Control/MLens.hs
+++ b/src/Control/MLens.hs
@@ -1,16 +1,10 @@
--- {-# LANGUAGE ExistentialQuantification #-}
--- {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 -- | The main monadic lens interface, ideally users should import only this module.
 module Control.MLens
     ( -- * Data types
       MLens
-    , Lens
     , Ref
 
-    -- * Lens operations
-    , getL, setL, modL
-    , readRef, writeRef, modRef
-
     -- * Lens transformations
     , mapMLens
     , (.)
@@ -18,14 +12,22 @@
     , joinML
     , memoMLens
 
-    -- * Lens creation
+    -- * Lens destruction
+    , runMLens
+    , runRef
+
+    -- * Lens construction
     , lensStore
     , NewRef (..)
     , ExtRef (..)
     , Ext, runExt, runExt_
 
     -- * Derived constructs
-    -- ** Pure lenses, built with @lensStore@
+    -- ** Lens operations
+    , getL, setL, modL
+    , readRef, writeRef, modRef
+
+    -- ** Pure lenses, defined with @lensStore@
     , id
     , unitLens
     , fstLens, sndLens
@@ -33,15 +35,16 @@
     , listLens
     , ithLens
 
-    -- ** Impure lenses, built with @lensStore@
+    -- ** Impure lenses, defined with @lensStore@
     , forkLens
     , justLens
     , showLens
 
     -- ** Other derived construts
-    , lens
+    , Lens
     , fromLens
     , toLens
+    , lens
     , joinLens
     , undoTr
     , memoRead
@@ -49,14 +52,26 @@
 
     -- * Auxiliary definitions
     , Morph
+
+    -- ** Consistency tests
+    , testExt
     ) where
 
 import Control.Category
+import Control.Monad.Writer
 import Prelude hiding ((.), id)
 
 import Data.MLens
 import Data.MLens.Ref
 import Control.MLens.ExtRef
+import Control.MLens.ExtRef.Test
 import Control.MLens.ExtRef.Pure
+
+newtype ExtTest i a = ExtTest { unExtTest :: Ext i (Writer [String]) a }
+    deriving (Monad, MonadWriter [String], NewRef, ExtRef)
+
+-- | Consistency tests for @Ext@, should give an empty list of errors.
+testExt :: [String]
+testExt = mkTests (\t -> execWriter $ runExt $ unExtTest t)
 
 
diff --git a/src/Control/MLens/ExtRef.hs b/src/Control/MLens/ExtRef.hs
--- a/src/Control/MLens/ExtRef.hs
+++ b/src/Control/MLens/ExtRef.hs
@@ -17,27 +17,25 @@
 import Data.MLens.Ref
 
 {- |
-Suppose that @k@ is a pure lens, and
-
-@s <- extRef r k a0@.
+Suppose that @r@ is a pure reference and @k@ is a pure lens.
 
 The following laws should hold:
 
- *  @s@ is a pure reference.
+ *  @(extRef r k a0 >>= readRef)@ === @(readRef r >>= setL k a0)@
 
- *  @(k . s)@ behaves exactly as @r@.
+ *  @(extRef r k a0 >> readRef r)@ === @(readRef r)@
 
- *  The initial value of @s@ is the result of @(readRef r >>= setL k a0)@.
+Given @s <- extRef r k a0@, the following laws should hold:
 
-Moreover, @(extRef r k a0)@ should not change the value of @r@.
+ *  @s@ is a pure reference
 
-The following two operations should be identical:
+ *  @(k . s)@ === @r@
 
-@newRew x@
+Law for @newRef@ when @extRef@ is defined:
 
-@extRef unitLens unitLens x@
+ *  @(newRew x)@ === @(extRef unitLens unitLens x)@
 
-For examples, see "Control.MLens.ExtRef.Pure.Test".
+For basic usage examples, look into the source of "Control.MLens.ExtRef.Pure.Test".
 -}
 class NewRef m => ExtRef m where
     extRef :: Ref m b -> MLens m a b -> a -> m (Ref m a)
diff --git a/src/Control/MLens/ExtRef/Pure/Test.hs b/src/Control/MLens/ExtRef/Pure/Test.hs
deleted file mode 100644
--- a/src/Control/MLens/ExtRef/Pure/Test.hs
+++ /dev/null
@@ -1,19 +0,0 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
--- | Tests for the reference implementation of the @ExtRef@ interface.
-module Control.MLens.ExtRef.Pure.Test
-    ( -- * Test suit 
-      tests
-    ) where
-
-import Control.Monad.Writer
-
-import Control.MLens.ExtRef
-import Control.MLens.ExtRef.Test
-import Control.MLens.ExtRef.Pure
-
-
-newtype E i a = E { unE :: Ext i (Writer [String]) a } deriving (Monad, MonadWriter [String], NewRef, ExtRef)
-
-tests :: [String]
-tests = mkTests (\t -> execWriter $ runExt $ unE t)
-
diff --git a/src/Control/MLens/NewRef.hs b/src/Control/MLens/NewRef.hs
--- a/src/Control/MLens/NewRef.hs
+++ b/src/Control/MLens/NewRef.hs
@@ -19,7 +19,7 @@
 {- |
 Laws for @NewRef@:
 
- *  Any reference created by @newRef@ should satisfy the reference laws given in "Data.MLens.Ref".
+ *  Any reference created by @newRef@ should satisfy the reference laws.
 -}
 class (Monad m) => NewRef m where
     newRef :: a -> m (Ref m a)
diff --git a/src/Control/MLens/Unsafe.hs b/src/Control/MLens/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/MLens/Unsafe.hs
@@ -0,0 +1,15 @@
+-- | This module exports unsafe definitions, like the @NewRef@ instance for @IO@ which does not fulfil the @NewRef@ laws in a multi-threaded environment.
+module Control.MLens.Unsafe
+    ( -- * Unsafe references
+      fileRef
+    , fileRef_
+    , logConsoleLens
+    , logMLens
+    -- * Auxiliary definitions
+    , logFile
+    ) where
+
+import Data.MLens.Ref
+import Control.MLens.NewRef.Unsafe ()
+
+
diff --git a/src/Data/MLens.hs b/src/Data/MLens.hs
--- a/src/Data/MLens.hs
+++ b/src/Data/MLens.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE RankNTypes #-}
 module Data.MLens
     ( -- * Monadic lenses data type
-      MLens (MLens)
+      MLens (..)
 
     -- * Side-effect free lenses
     , Lens
@@ -46,16 +46,15 @@
 {-|
 Monadic lenses.
 
-The following representations would be also good for @(MLens m a b)@:
+Laws for pure monadic lenses:
 
- *  @a -> m (Store b (m a))@
+ *  set-get: @(setL l b a >>= getL l)@ === @(setL l b a >> return b)@
 
- *  @forall f . Functor f => (b -> m (f (m b))) -> a -> m (f (m a))@
+ *  get-set: @(getL l a >>= \b -> setL l b a)@  ===  @(return a)@
 
- *  @(a -> m b, b -> a -> m a)@
+ *  set-set: @(setL l b a >>= setL l b')@ ===  @(setL l b' a)@
 
-The last representation has no efficient composition operation
-(the set operation on composition of n lenses use O(n * n) get operations with the last representation).
+For example, @fstLens@ and @(fstLens . fstLens)@ fulfil these laws.
 
 Using lenses which do not fulfil the lens laws are safe,
 but one should take extra care when doing program transformations
@@ -68,24 +67,26 @@
 TODO: List laws, document which laws hold for each lenses.
 -}
 newtype MLens m a b
-    = MLens (a -> m (b, b -> m a))
-
-{-|
-Side-effect free lenses.
+    = MLens { runMLens :: a -> m (b, b -> m a) }
+{-
+The following representations would be also good for @(MLens m a b)@:
 
-The following representations would be also good for @(Lens a b)@:
+ *  @a -> m (Store b (m a))@
 
- *  @forall m . Monad m => MLens m a b@
+ *  @forall f . Functor f => (b -> m (f (m b))) -> a -> m (f (m a))@
 
-Laws for pure monadic lenses:
+ *  @(a -> m b, b -> a -> m a)@
 
- *  set-get: @(setL l b a >>= getL l)@ === @(setL l b a >> return b)@
+The last representation has no efficient composition operation
+(the set operation on composition of n lenses use O(n * n) get operations with the last representation).
+-}
 
- *  get-set: @(getL l a >>= \b -> setL l b a)@  ===  @(return a)@
+{-|
+Side-effect free lenses.
 
- *  set-set: @(setL l b a >>= setL l b')@ ===  @(setL l b' a)@
+The following representations would be also good for @(Lens a b)@:
 
-For example, @fstLens@ and @(fstLens . fstLens)@ fulfil these laws.
+ *  @forall m . Monad m => MLens m a b@
 -}
 type Lens a b
     = MLens Identity a b
@@ -101,19 +102,19 @@
 lensStore f = MLens $ return . g . f where
     g (b, ba) = (b, return . ba)
 
--- | Impure (but effect-free) lens constuctor, built on @lensStore@.
+-- | Impure (but effect-free) lens constuctor, defined with @lensStore@.
 lens :: Monad m => (a -> b) -> (b -> a -> a) -> MLens m a b
 lens get set = lensStore $ \a -> (get a, flip set a)
 
 getL :: Monad m => MLens m a b -> a -> m b
-getL (MLens f) a = f a >>= return . fst
+getL k a = runMLens k a >>= return . fst
 
 setL :: Monad m => MLens m a b -> b -> a -> m a
-setL (MLens f) b a = f a >>= ($ b) . snd
+setL k b a = runMLens k a >>= ($ b) . snd
 
 modL :: Monad m => MLens m b a -> (a -> a) -> b -> m b
-modL (MLens g) f b = do
-    (x, h) <- g b
+modL k f b = do
+    (x, h) <- runMLens k b
     h (f x)
 
 instance Monad m => Category (MLens m) where
@@ -147,9 +148,7 @@
     return (x, f . s)
 
 joinML :: Monad m => (a -> m (MLens m a b)) -> MLens m a b
-joinML r = MLens $ \x -> do
-    MLens q <- r x
-    q x
+joinML r = MLens $ \x -> r x >>= ($ x) . runMLens
 
 -- | It would be possible to define a @Monad@ instance for @(MLens m a)@ too, but monad laws would not hold.
 joinLens :: Monad m => MLens m a (MLens m a b) -> MLens m a b
diff --git a/src/Data/MLens/Ref.hs b/src/Data/MLens/Ref.hs
--- a/src/Data/MLens/Ref.hs
+++ b/src/Data/MLens/Ref.hs
@@ -6,6 +6,7 @@
     , Ref
 
     -- * Reference operations
+    , runRef
     , readRef, writeRef, modRef
 
     -- * Some impure @IO@ referenceses
@@ -31,16 +32,7 @@
 data Unit = Unit deriving (Eq, Show)
 
 {- |
-Note that references lenses can be composed with lenses.
-For example, if
-
-@r :: Ref m (a,b)@
-
-then
-
-@fstLens . r :: Ref m a@
-
-Reference laws for pure references:
+Laws for pure references:
 
  *  @(readRef r >> return ())@ === @(return ())@
 
@@ -51,17 +43,30 @@
  *  @(writeRef r a >> writeRef r a')@ === @(writeRef r a')@
 
 These laws are equivalent to the get-no-effect, set-get, get-set and set-set laws for monadic lenses.
+
+Reference lenses can be composed with lenses.
+For example, if
+
+@r :: Ref m (a,b)@
+
+then
+
+@fstLens . r :: Ref m a@
 -}
 type Ref m a = MLens m Unit a
 
+runRef :: Monad m => Ref m a -> m (a, a -> m ())
+runRef r = liftM f $ runMLens r Unit where
+    f (a, m) = (a, \a -> m a >> return ())
+
 readRef :: Monad m => Ref m a -> m a
-readRef k = getL k Unit
+readRef = liftM fst . runRef
 
 writeRef :: Monad m => Ref m a -> a -> m ()
-writeRef r a = setL r a Unit >> return ()
+writeRef r a = runRef r >>= ($ a) . snd
 
 modRef :: Monad m => Ref m a -> (a -> a) -> m ()
-k `modRef` f = modL k f Unit >> return ()
+k `modRef` f = runRef k >>= \(a, m) -> m $ f a
 
 -- | Using @fileRef@ is safe if the file is not used concurrently.
 fileRef :: FilePath -> IO (Ref IO String)
@@ -69,16 +74,16 @@
 
 -- | Note that if you write @Nothing@, the file is deleted.
 fileRef_ :: FilePath -> IO (Ref IO (Maybe String))
-fileRef_ f = return $ MLens $ \Unit -> do
+fileRef_ f = return $ MLens $ \unit -> do
     b <- doesFileExist f
     if b then do
             xs <- readFile f
-            length xs `seq` return (Just xs, wr)
-         else return (Nothing, wr)
+            length xs `seq` return (Just xs, wr unit)
+         else return (Nothing, wr unit)
  where
-    wr mb = do
+    wr unit mb = do
         maybe (doesFileExist f >>= \b -> when b (removeFile f)) (writeFile f) mb
-        return Unit
+        return unit
 
 logMLens :: Monad m => (a -> m ()) -> (a -> m ()) -> MLens m a a
 logMLens getLog setLog = MLens $ \a -> getLog a >> return (a, \b -> setLog b >> return b)
diff --git a/src/GUI/MLens/Gtk/IO.hs b/src/GUI/MLens/Gtk/IO.hs
--- a/src/GUI/MLens/Gtk/IO.hs
+++ b/src/GUI/MLens/Gtk/IO.hs
@@ -13,7 +13,7 @@
 import Graphics.UI.Gtk
 
 import Control.MLens
-import Control.MLens.NewRef.Unsafe ()
+import Control.MLens.Unsafe ()
 import GUI.MLens.Gtk.Interface
 
 ------------------
diff --git a/src/GUI/MLens/Gtk/Interface.hs b/src/GUI/MLens/Gtk/Interface.hs
--- a/src/GUI/MLens/Gtk/Interface.hs
+++ b/src/GUI/MLens/Gtk/Interface.hs
@@ -7,7 +7,7 @@
 
 import Control.Monad.Free
 
-import Data.MLens.Ref
+import Control.MLens
 
 -- | Interface description parametrized by a monad
 data I m
