diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,3 @@
+# v0.1.0.0
+
+Initial release.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Patrick Thomson (c) 2018
+
+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 Patrick Thomson here 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,40 @@
+# fused-effects-lens
+
+This package provides an interface to the [lens](github.com/ekmett/lens) library that is compatible with [fused-effects](github.com/robrix/fused-effects). The standard formulation of `lens` combinators for operating in `MonadState` contexts—`use`, `.=`, et al—rely on `mtl` for `MonadState` and `MonadReader`, which is not applicable to `Reader` and `State` effects.
+
+This package is meant to be used alongside `lens`, like so:
+
+``` haskell
+import Control.Lens hiding (view, use, assign)
+import Control.Effect.Lens (view, use, assign)
+```
+
+## Example
+
+Given a `Context` type that we will use in a `State` effect:
+
+``` haskell
+data Context = Context
+  { _amount :: Int
+  , _disabled :: Bool
+  } deriving (Eq, Show)
+  
+makeLenses ''Context
+```
+
+We can can use the `use` combinators to extract a lens target from the current state, and `assign` to write to a field of that state:
+
+``` haskell
+stateTest :: (Member (State Context) sig, Carrier sig m, Monad m) => m Int
+stateTest = do
+  initial <- use amount
+  assign amount (initial + 1)
+  assign disabled True
+  use amount
+```
+
+You can find a more complete example, including one that works with multiple `State` constraints in a single computation, in the `test` directory.
+
+## License
+
+BSD3, like `fused-effects`.
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/fused-effects-lens.cabal b/fused-effects-lens.cabal
new file mode 100644
--- /dev/null
+++ b/fused-effects-lens.cabal
@@ -0,0 +1,36 @@
+name:                fused-effects-lens
+version:             0.1.0.0
+synopsis:            Monadic lens combinators for fused-effects.
+description:         Provides combinators for the lens-based manipulation of state and context types provided by the fused-effects library, similar to those provided for mtl-based monad transformers.
+homepage:            https://github.com/patrickt/fused-effects-lens#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Patrick Thomson
+maintainer:          patrickt@github.com
+copyright:           2018 Patrick Thomson
+category:            Web
+build-type:          Simple
+cabal-version:       >=1.10
+extra-source-files:
+  README.md
+  CHANGES.md                 
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Control.Effect.Lens
+  default-language:    Haskell2010
+  build-depends:       base >= 4.7 && < 5
+                     , lens >= 4   && < 5
+                     , fused-effects >= 0.1.2 && < 1
+  ghc-options:         -Wall
+
+test-suite test
+  type:                exitcode-stdio-1.0
+  main-is:             Main.hs
+  hs-source-dirs:      test
+  default-language:    Haskell2010
+  build-depends:       base >=4.7 && < 5.0
+                     , fused-effects-lens
+                     , lens >=4   && < 5
+                     , fused-effects >= 0.1.2 && < 1
+                     , hspec >= 2.4.1
diff --git a/src/Control/Effect/Lens.hs b/src/Control/Effect/Lens.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Effect/Lens.hs
@@ -0,0 +1,96 @@
+{-# LANGUAGE FlexibleContexts, RankNTypes #-}
+
+module Control.Effect.Lens
+  ( view
+  , views
+  , use
+  , uses
+  , assign
+  , (.=)
+  , modifying
+  , (%=)
+  ) where
+
+import Control.Effect
+import qualified Control.Effect.State as State
+import qualified Control.Effect.Reader as Reader
+import qualified Control.Lens as Lens
+import Control.Lens.Getter (Getting)
+import Control.Lens.Setter (ASetter)
+
+-- | View the value pointed to by a 'Control.Lens.Getter.Getter',
+-- 'Control.Lens.Iso.Iso' or 'Control.Lens.Lens.Lens' or the result of
+-- folding over all the results of a 'Control.Lens.Fold.Fold' or
+-- 'Control.Lens.Traversal.Traversal' corresponding to the 'Reader'
+-- context of the given monadic carrier.
+view :: forall r a sig m . (Member (Reader r) sig, Carrier sig m, Functor m) => Getting a r a -> m a
+view l = Reader.asks (Lens.view l)
+{-# INLINE view #-}
+
+-- | View a function of the value pointed to by a
+-- 'Control.Lens.Getter.Getter', 'Control.Lens.Iso.Iso' or
+-- 'Control.Lens.Lens.Lens' or the result of folding over all the
+-- results of a 'Control.Lens.Fold.Fold' or
+-- 'Control.Lens.Traversal.Traversal' corresponding to the 'Reader'
+-- context of the given monadic carrier.
+-- 
+-- This is slightly more general in lens itself, but should suffice for our purposes.
+views :: (Member (Reader s) sig, Carrier sig m, Functor m) => Getting a s a -> (a -> b) -> m b
+views l f = fmap f (Reader.asks (Lens.view l))
+{-# INLINE views #-}
+
+-- | Extract the target of a 'Control.Lens.Lens',
+-- 'Control.Lens.Iso.Iso', or 'Control.Lens.Getter.Getter' from the,
+-- or use a summary of a 'Control.Lens.Fold.Fold' or
+-- 'Control.Lens.Traversal.Traversal' that points to a monoidal value.
+use :: forall s a sig m . (Member (State s) sig, Carrier sig m, Monad m) => Getting a s a -> m a
+use l = State.gets (Lens.view l)
+{-# INLINE use #-}
+
+-- | Use a function of the target of a 'Control.Lens.Lens.Lens',
+-- 'Control.Lens.Iso.Iso', or 'Control.Lens.Getter.Getter' in the
+-- current state, or use a summary of a 'Control.Lens.Fold.Fold' or
+-- 'Control.Lens.Traversal.Traversal' that points to a monoidal value.
+uses :: (Carrier sig f, Functor f, Member (State s) sig) => Getting a s a -> (a -> b) -> f b
+uses l f = fmap f (State.gets (Lens.view l))
+{-# INLINE uses #-}
+
+-- | Replace the target of a 'Control.Lens.Lens.Lens' or all of the
+-- targets of a 'Control.Lens.Setter.Setter' or
+-- 'Control.Lens.Traversal.Traversal' in our monadic state with a new
+-- value, irrespective of the old.
+--
+-- This is a prefix version of '.='.
+assign :: forall s a b sig m . (Member (State s) sig, Carrier sig m, Monad m) => ASetter s s a b -> b -> m ()
+assign l b = State.modify (Lens.set l b)
+{-# INLINE assign #-}
+
+-- | Replace the target of a 'Control.Lens.Lens.Lens' or all of the
+-- targets of a 'Control.Lens.Setter.Setter' or
+-- 'Control.Lens.Traversal.Traversal' in our monadic state with a new
+-- value, irrespective of the old.
+--
+-- This is an infix version of 'assign'.
+infixr 4 .=
+(.=) :: forall s a b sig m . (Member (State s) sig, Carrier sig m, Monad m) => ASetter s s a b -> b -> m ()
+(.=) = assign
+{-# INLINE (.=) #-}
+
+-- | Map over the target of a 'Control.Lens.Lens.Lens' or all of the
+-- targets of a 'Control.Lens.Setter.Setter' or
+-- 'Control.Lens.Traversal.Traversal' in our monadic state.
+--
+-- This is a prefix version of '%='.
+modifying :: forall s a b sig m . (Member (State s) sig, Carrier sig m, Monad m) => ASetter s s a b -> (a -> b) -> m ()
+modifying l f = State.modify (Lens.over l f)
+{-# INLINE modifying #-}
+
+-- | Map over the target of a 'Control.Lens.Lens.Lens' or all of the
+-- targets of a 'Control.Lens.Setter.Setter' or
+-- 'Control.Lens.Traversal.Traversal' in our monadic state.
+--
+-- This is an infix version of 'modifying'.
+infixr 4 %=
+(%=) :: forall s a b sig m . (Member (State s) sig, Carrier sig m, Monad m) => ASetter s s a b -> (a -> b) -> m ()
+(%=) = modifying
+{-# INLINE (%=) #-}
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE TypeApplications, FlexibleContexts, MultiParamTypeClasses, TemplateHaskell, TypeFamilies, FlexibleInstances #-}
+
+module Main where
+
+import Control.Effect
+import Control.Effect.Reader
+import Control.Effect.State
+import Control.Lens.Wrapped
+import Control.Lens.TH
+import Test.Hspec
+
+import Control.Effect.Lens
+
+data Context = Context
+  { _amount :: Int
+  , _sweatshirt :: Bool
+  } deriving (Eq, Show)
+
+initial :: Context
+initial = Context 0 False
+
+makeLenses ''Context
+
+stateTest :: (Member (State Context) sig, Carrier sig m, Monad m) => m Int
+stateTest = do
+  initial <- use amount
+  assign amount (initial + 1)
+  assign sweatshirt True
+  use amount
+
+newtype Foo = Foo { _unFoo :: Int } deriving (Eq, Show)
+
+makeWrapped ''Foo
+
+newtype Bar = Bar { _unBar :: Float } deriving (Eq, Show)
+
+makeWrapped ''Bar
+
+doubleStateTest :: (Member (State Bar) sig, Member (State Foo) sig, Carrier sig m, Monad m) => m Int
+doubleStateTest = do
+  assign @Foo _Wrapped 5
+  assign @Bar _Wrapped 30.5
+  pure 50
+
+readerTest :: (Member (Reader Context) sig, Carrier sig m, Monad m) => m Int
+readerTest = succ <$> view amount
+
+spec :: Spec
+spec = describe "use/assign" $ do
+  it "should modify stateful variables" $ do
+    let result = run $ runState initial stateTest
+    result `shouldBe` (Context 1 True, 1)
+
+  it "works in the presence of polymorphic lenses with -XTypeAnnotations" $ do
+    let result = run $ runState (Bar 5) $ runState (Foo 500) doubleStateTest
+    result `shouldBe` (Bar 30.5, (Foo 5, 50))
+
+  it "should read from an environment" $ do
+    let result = run $ runReader initial readerTest
+    result `shouldBe` 1
+
+main :: IO ()
+main = hspec $ describe "Control.Effect.Lens" spec
