diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for predicate-transformers
+
+## 0.1.0.0 -- 2019-10-05
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2019, Edmund Noble
+
+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 Edmund Noble 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/predicate-transformers.cabal b/predicate-transformers.cabal
new file mode 100644
--- /dev/null
+++ b/predicate-transformers.cabal
@@ -0,0 +1,28 @@
+cabal-version:       2.4
+
+name:                predicate-transformers
+version:             0.1.0.0
+synopsis:            A library for writing predicates and transformations over predicates in Haskell
+description:
+  This package provides ways to write predicates such that they compose nicely and are easy to debug.
+-- bug-reports:
+license:             BSD-3-Clause
+license-file:        LICENSE
+author:              Edmund Noble
+maintainer:          edmundnoble@gmail.com
+-- copyright:
+category:            Data
+extra-source-files:  CHANGELOG.md
+source-repository head
+  type: git
+  location: https://gitlab.com/edmundnoble/predicate-transformers
+
+library
+  exposed-modules: PredicateTransformers
+  -- other-modules:
+  -- other-extensions:
+  build-depends:       base ^>=4.11 || ^>=4.12 || ^>=4.13
+                      ,lens ^>=4.17 || ^>=4.18
+                      ,adjunctions ^>=4.2 || ^>=4.3 || ^>=4.4
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/PredicateTransformers.hs b/src/PredicateTransformers.hs
new file mode 100644
--- /dev/null
+++ b/src/PredicateTransformers.hs
@@ -0,0 +1,95 @@
+-- | This library is based on the notion of a predicate transformer, the below
+-- type @PT a b@, which is a function from @a@ to predicates on @b@.
+-- They act as a sort of compositional "matcher language".
+-- Composing these predicate transformers is meant to be analogous to composing optics
+-- and there are utilities for using predicate transformers with (`lens`-style) optics.
+module PredicateTransformers where
+
+import Prelude hiding (all)
+import Control.Lens hiding (index, zoom)
+import Data.Foldable(toList)
+import Data.Functor.Rep(Representable(..))
+import Debug.Trace
+
+-- |A convenient alias for predicates.
+type Pred a = a -> Bool
+
+-- |Predicate transformers form a category where composition is ordinary function
+-- composition.
+-- Multiple are already provided by the standard library,
+-- for instance `Data.Foldable.all` and `Data.Foldable.any`.
+type PT a b = Pred a -> Pred b
+
+-- |Functor from Hask^op to PT.
+function :: (b -> a) -> PT a b
+function = flip (.)
+
+-- |Operate on the target of a prism, or fail.
+match :: APrism s t a b -> PT a s
+match p pred s = either (const False) pred (matching p s)
+
+-- |Operate on the target of a getter.
+getter :: Getting a s a -> PT a s
+getter g = function (view g)
+
+-- |Invert a predicate.
+nay :: PT a a
+nay = (not .)
+
+-- |Operate on the `Just` branch of a `Maybe`, or fail.
+just :: PT a (Maybe a)
+just = match _Just
+
+-- |Operate on the `Left` branch of an `Either`, or fail.
+left :: PT e (Either e a)
+left = match _Left
+
+-- |Operate on the `Right` branch of an `Either`, or fail.
+right :: PT a (Either e a)
+right = match _Right
+
+-- |Operate on the last value in a list, or fail if it's not present.
+endingWith :: PT a [a]
+endingWith _ [] = False
+endingWith p xs = p $ last xs
+
+-- |Operate on the first value in a list, or fail if it's not present.
+startingWith :: PT a [a]
+startingWith p (x:_) = p x
+startingWith _ [] = False
+
+-- |Require that a list has a single element, and operate on that element.
+only :: PT a [a]
+only p [x] = p x
+only _ _ = False
+
+-- |Given a list of predicates and a list of values, ensure that each predicate holds for each respective value.
+-- Fails if the two lists have different lengths.
+dist :: [Pred a] -> Pred [a]
+dist (p:ps) (x:xs) = p x && dist ps xs
+dist [] [] = True
+dist _ _ = False
+
+-- |Given a functor-full of predicates, and a functor-full of values, ensure that the structures
+-- of the two functors match and apply all of the predicates to all of the values.
+-- Generalized version of `dist`.
+distF ::
+    (Eq (f ()), Functor f, Foldable f) =>
+    f (Pred a) -> Pred (f a)
+distF preds values =
+    (() <$ preds) == (() <$ values) &&
+    dist (toList preds) (toList values)
+
+-- |Given a representable functor-full of predicates, and a functor-full of values,
+-- yield a representable functor-full of booleans. Similar to `distF`.
+distRep :: Representable f =>
+    f (a -> Bool) -> f a -> f Bool
+distRep pr fa = tabulate (\r -> index pr r $ index fa r)
+
+-- |Sugar for tupling.
+(==>) :: a -> b -> (a, b)
+(==>) = (,)
+
+-- |Prints the input of a predicate, for debugging.
+traced :: Show a => PT a a
+traced = function traceShowId
