diff --git a/refractor.cabal b/refractor.cabal
--- a/refractor.cabal
+++ b/refractor.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.4
 name:                refractor
-version:             0.0.0.0
+version:             0.0.1.0
 synopsis:            See README for more info
 description:         See README for more info
 homepage:            https://github.com/strake/refractor.hs
@@ -18,8 +18,11 @@
 
 common c
   build-depends:       base ^>= 4.13
-  ghc-options:         
-                     -Wall
+                     , base-unicode-symbols ^>= 0.2.4.2
+                     , category ^>= 0.2.5
+                     , hs-functors ^>= 0.1.6
+                     , transformers ^>= 0.5
+  ghc-options:       -Wall
                      -Wcompat
                      -Wredundant-constraints
                      -Wno-name-shadowing
@@ -45,6 +48,7 @@
                        DeriveFunctor
                        DeriveFoldable
                        DeriveTraversable
+                       RankNTypes
 
 library
   import:              c
diff --git a/src/Control/Refractor.hs b/src/Control/Refractor.hs
--- a/src/Control/Refractor.hs
+++ b/src/Control/Refractor.hs
@@ -1,1 +1,91 @@
-module Control.Refractor where
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE QuantifiedConstraints #-}
+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
+module Control.Refractor
+  ( Lens, Iso,
+    lens, iso,
+    gets, get, set, modify,
+    toListOf, foldrOf, foldlOf, mapAccumLOf, mapAccumROf,
+    fstL, sndL, swapL, unitL, constL
+  ) where
+
+import Prelude hiding (Functor (..), id, map)
+
+import Control.Applicative
+import Control.Applicative.Backwards (Backwards (..))
+import Control.Categorical.Functor
+import Control.Category
+import Control.Category.Dual
+import Control.Category.Unicode
+import Control.Monad.Trans.State (State, state, runState)
+import Data.Functor.Identity
+import qualified Data.Monoid as Monoid (Dual (..))
+import Data.Morphism.Endo
+import Data.Profunctor
+import Data.Proxy
+import Data.Tuple (swap)
+
+type Refractor s t f α β a b = s a (f b) -> t α (f β)
+
+type Lens s t α β a b = ∀ f . Functor s t f => Refractor s t f α β a b
+
+type Iso σ τ s t α β a b = ∀ p f . (Functor (Dual σ) (NT (->)) p, ∀ x . Functor s (->) (p x), Functor τ s f) => Refractor p p f α β a b
+
+lens :: (α -> a) → (b → α → β) → Lens (->) (->) α β a b
+lens get set ret = liftA2 map (flip set) (ret ∘ get)
+
+iso :: ∀ σ τ s t α β a b . Proxy s -> σ α a → τ b β → Iso σ τ s t α β a b
+iso _ f g = map (map g :: s _ _) ∘ nt (map (Dual f))
+
+get :: ((a → Const a b) → α → Const a β) → α → a
+get l = gets l id
+
+gets :: ((a -> Const c b) -> α -> Const c β) -> (a -> c) -> α -> c
+gets l f = getConst ∘ l (Const ∘ f)
+
+set :: ((a → Identity b) → α → Identity β) → b → α → β
+set l = modify l ∘ pure
+
+modify :: ((a → Identity b) → α → Identity β) → (a → b) → α → β
+modify l f = runIdentity ∘ l (Identity ∘ f)
+
+-- foldOf :: Monoid a => Getting a α β a b -> α -> a
+-- foldOf = get
+
+-- foldMapOf :: Getting c α β a b -> (a -> c) -> α -> c
+-- foldMapOf = gets
+
+toListOf :: Getting (Endo (->) [a]) α β a b -> α -> [a]
+toListOf l = foldrOf l (:) []
+
+foldrOf :: Getting (Endo (->) c) α β a b -> (a -> c -> c) -> c -> α -> c
+foldrOf l f z₀ = flip endo z₀ ∘ gets l (Endo ∘ f)
+
+foldlOf :: Getting (Monoid.Dual (Endo (->) c)) α β a b -> (c -> a -> c) -> c -> α -> c
+foldlOf l f z₀ = flip endo z₀ ∘ Monoid.getDual ∘ gets l (Monoid.Dual ∘ Endo ∘ flip f)
+
+-- foldMapAccumOf :: Monoid c => ((a -> (c, b)) -> α -> (c, β)) -> (a -> (c, b)) -> α -> (c, β)
+-- foldMapAccumOf = id
+
+mapAccumROf :: ((a -> State c b) -> α -> State c β) -> (a -> c -> (c, b)) -> c -> α -> (c, β)
+mapAccumROf l f z₀ = swap ∘ flip runState z₀ ∘ l (state ∘ (swap ∘) ∘ f)
+
+mapAccumLOf :: ((a -> Backwards (State c) b) -> α -> Backwards (State c) β) -> (c -> a -> (c, b)) -> c -> α -> (c, β)
+mapAccumLOf l f z₀ = swap ∘ flip runState z₀ ∘ forwards ∘ l (Backwards ∘ state ∘ (swap ∘) ∘ flip f)
+
+type Getting r α β a b = (a -> Const r b) -> α -> Const r β
+
+fstL :: Lens (->) (->) (a, c) (b, c) a b
+fstL = swapL ∘ sndL
+
+sndL :: Lens (->) (->) (a, b) (a, c) b c
+sndL f = id *** f >>> uncurry (map ∘ (,))
+
+swapL :: Iso (->) (->) (->) (->) (a, b) (c, d) (b, a) (d, c)
+swapL = iso (Proxy :: Proxy (->)) swap swap
+
+unitL :: Lens (->) (->) α α () ()
+unitL = lens (pure ()) (\ () -> id)
+
+constL :: Iso (->) (->) (->) (->) (Const a α) (Const b β) a b
+constL = iso (Proxy :: Proxy (->)) getConst Const
