diff --git a/Data/Lens/IxSet.hs b/Data/Lens/IxSet.hs
new file mode 100644
--- /dev/null
+++ b/Data/Lens/IxSet.hs
@@ -0,0 +1,63 @@
+module Data.Lens.IxSet (ixLens) where
+
+import Data.IxSet
+import Data.Lens.Common
+import Data.Typeable
+
+-- |Focus on a key in an indexed set.
+--
+-- Given an 'IxSet' of people:
+--
+-- > people = fromList [ Person (FirstName "Edward A.") (LastName "Kmett")
+-- >                   , Person (FirstName "Simon") (LastName "P. Jones")
+-- >                   ]
+--
+-- We can now work with indices as lenses and fix Simon's last name:
+--
+-- > people' = lastName . ixLens (FirstName "Simon") ^= (LastName "Peyton-Jones") people
+--
+-- Perhaps more commonly you're working with an IxSet from inside a state monad such as with acid-state.  In that case usage is even easier:
+--
+-- > changeLastName = lastName . ixLens (FirstName "Simon") %= LastName "Peyton-Jones"
+--
+-- Feels backwards?  Lens composition uses 'Category' so we can flip it
+-- around more intuitively using the composition arrows instead:
+--
+-- > changeLastName' = ixLens (FirstName "Simon") >>> lastName %= LastName "Peyton-Jones"
+--
+-- Here's the missing boilerplate:
+--
+-- > {-# LANGUAGE DeriveDataTypeable #-}
+-- > {-# LANGUAGE TemplateHaskell #-}
+-- >
+-- > import Prelude hiding ((.))
+-- > import Control.Category
+-- > import Data.Data
+-- >
+-- > import Data.Lens
+-- > import Data.Lens.Template
+-- > import Data.IxSet
+-- >
+-- > data Person = Person { _firstName :: FirstName
+-- >                      , _lastName  :: LastName
+-- >                      } deriving (Show, Eq, Ord, Data, Typeable)
+-- >
+-- > mkLens ''Person
+-- >
+-- > newtype FirstName = FirstName String
+-- >   deriving (Show, Eq, Ord, Data, Typeable)
+-- >
+-- > newtype LastName = LastName String
+-- >   deriving (Show, Eq, Ord, Data, Typeable)
+-- >
+-- > instance Indexable Person where
+-- >   empty = ixSet [ ixGen (Proxy :: Proxy FirstName)
+-- >                 , ixGen (Proxy :: Proxy LastName)
+-- >                 ]
+ixLens :: (Indexable a, Typeable a, Typeable k, Ord a)
+       => k -> Lens (IxSet a) (Maybe a)
+ixLens k = lens get set
+  where
+    get          = getOne . getEQ k
+    set (Just v) = updateIx k v
+    set Nothing  = deleteIx k
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2011, Dag Odenhall
+
+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 Dag Odenhall 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/data-lens-ixset.cabal b/data-lens-ixset.cabal
new file mode 100644
--- /dev/null
+++ b/data-lens-ixset.cabal
@@ -0,0 +1,28 @@
+Name          : data-lens-ixset
+Version       : 0.1.0
+Synopsis      : A Lens for IxSet
+Description   : Integrates Data.IxSet with Data.Lens.
+Homepage      : https://github.com/dag/data-lens-ixset
+License       : BSD3
+License-file  : LICENSE
+Author        : Dag Odenhall
+Maintainer    : dag.odenhall@gmail.com
+Category      : Control, Comonad, Data Structures
+Build-type    : Simple
+Cabal-version : >= 1.6
+
+Source-repository head
+  Type     : git
+  Location : git://github.com/dag/data-lens-ixset.git
+
+Library
+  GHC-Options     : -Wall
+  Exposed-modules : Data.Lens.IxSet
+  Build-depends   : base >= 4 && < 5,
+                    data-lens >= 2.0 && < 2.1,
+                    ixset >= 1.0 && < 1.1
+
+Executable test-data-lens-ixset
+  GHC-Options   : -Wall
+  Main-is       : test-data-lens-ixset.hs
+  Build-depends : QuickCheck >= 2.4 && < 2.5
diff --git a/test-data-lens-ixset.hs b/test-data-lens-ixset.hs
new file mode 100644
--- /dev/null
+++ b/test-data-lens-ixset.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+module Main where
+
+import Control.Monad
+import Data.Data
+import Data.IxSet
+import Data.Lens.Common
+import Data.Lens.IxSet
+import System.Exit
+import Test.QuickCheck
+import Test.QuickCheck.All
+
+data Person = Person FirstName LastName
+  deriving (Show, Eq, Ord, Data, Typeable)
+
+newtype FirstName = FirstName String
+  deriving (Show, Eq, Ord, Data, Typeable, Arbitrary)
+
+newtype LastName = LastName String
+  deriving (Show, Eq, Ord, Data, Typeable, Arbitrary)
+
+instance Indexable Person where
+  empty = ixSet [ ixGen (Proxy :: Proxy FirstName)
+                , ixGen (Proxy :: Proxy LastName)
+                ]
+
+prop_get_set :: FirstName -> LastName -> Bool
+prop_get_set fname lname = getL l (setL l p empty) == p
+  where
+    l = ixLens fname
+    p = Just $ Person fname lname
+
+prop_set_get :: FirstName -> LastName -> Bool
+prop_set_get fname lname = setL l (getL l ix) ix == ix
+  where
+    l  = ixLens fname
+    ix = fromList [Person fname lname]
+
+prop_set_set :: FirstName -> LastName -> LastName -> Bool
+prop_set_set fname lname1 lname2 =
+    setL l p1 (setL l p2 empty) == setL l p1 empty
+  where
+    l  = ixLens fname
+    p1 = Just $ Person fname lname1
+    p2 = Just $ Person fname lname2
+
+main :: IO ()
+main = do
+  success <- $quickCheckAll
+  unless success exitFailure
