diff --git a/examples/defaultsignature.hs b/examples/defaultsignature.hs
--- a/examples/defaultsignature.hs
+++ b/examples/defaultsignature.hs
@@ -22,7 +22,7 @@
   enumAll :: [t]
 
   default enumAll :: (ADT t, Constraints t EnumAll) => [t]
-  enumAll = concat $ createA (For :: For EnumAll) enumAll
+  enumAll = concat $ createA (For :: For EnumAll) [enumAll]
 
 instance EnumAll Bool
 instance EnumAll a => EnumAll (Maybe a)
diff --git a/examples/realworld.hs b/examples/realworld.hs
--- a/examples/realworld.hs
+++ b/examples/realworld.hs
@@ -3,12 +3,11 @@
 import Generics.OneLiner
 
 import Data.Monoid
-import Control.Lens (Traversal')
-import Data.Typeable
+-- import Control.Lens (Traversal')
+-- import Data.Typeable
 import Control.DeepSeq
 import Test.SmallCheck.Series
 import Control.Monad.Logic.Class
-import Control.Applicative
 import Control.Monad
 import Data.Hashable
 import Data.Functor.Contravariant
@@ -18,16 +17,7 @@
 import Test.QuickCheck.Arbitrary
 import Test.QuickCheck.Gen
 
--- http://hackage.haskell.org/package/lens-4.3.3/docs/Generics-Deriving-Lens.html
-whenCastableOrElse :: forall a b f. (Typeable a, Typeable b) => (b -> f b) -> (a -> f a) -> a -> f a
-whenCastableOrElse f g = maybe g (\Refl -> f) (eqT :: Maybe (a :~: b))
 
-tinplate :: forall t b. (Typeable b, Deep Typeable t) => Traversal' t b
-tinplate f
-  | isAtom (Proxy :: Proxy t) = f `whenCastableOrElse` pure
-  | otherwise = gtraverse (For :: For (Deep Typeable)) $ f `whenCastableOrElse` tinplate f
-
-
 -- http://hackage.haskell.org/package/deepseq-generics-0.1.1.1/docs/src/Control-DeepSeq-Generics.html
 -- This would work if the monoid instance of () would have been strict, now it doesn't...
 grnf :: (ADT t, Constraints t NFData) => t -> ()
@@ -41,12 +31,12 @@
   Fair fs <*> Fair as = Fair $ fs <~> as
 
 gseries :: forall t m. (ADT t, Constraints t (Serial m), MonadLogic m) => Series m t
-gseries = foldr ((\/) . decDepth . runFair) mzero $ createA (For :: For (Serial m)) (Fair series)
+gseries = foldr ((\/) . decDepth . runFair) mzero $ createA (For :: For (Serial m)) [Fair series]
 
 newtype CoSeries m a = CoSeries { runCoSeries :: forall r. Series m r -> Series m (a -> r) }
 instance Contravariant (CoSeries m) where
   contramap f (CoSeries g) = CoSeries $ fmap (. f) . g
-instance MonadLogic m => Divisible (CoSeries m) where
+instance Divisible (CoSeries m) where
   divide f (CoSeries g) (CoSeries h) = CoSeries $ \rs -> do
     rs' <- fixDepth rs
     f2 <- decDepthChecked (constM $ constM rs') (g $ h rs')
@@ -70,11 +60,7 @@
 
 -- http://hackage.haskell.org/package/binary-0.7.2.1/docs/Data-Binary.html
 gget :: (ADT t, Constraints t Binary) => Get t
-gget = getWord8 >>= \ix -> createA (For :: For Binary) get !! fromEnum ix
-
-instance Monoid Put where
-  mempty = return ()
-  mappend = (>>)
+gget = getWord8 >>= \ix -> createA (For :: For Binary) [get] !! fromEnum ix
 
 gput :: (ADT t, Constraints t Binary) => t -> Put
 gput t = putWord8 (toEnum (ctorIndex t)) <> gfoldMap (For :: For Binary) put t
@@ -89,9 +75,19 @@
   conquer = CoArb $ const id
 instance Decidable CoArb where
   choose f (CoArb g) (CoArb h) = CoArb $ \a -> case f a of
-    Left b -> variant 0 . g b
-    Right c -> variant 1 . h c
+    Left b -> variant (0::Int) . g b
+    Right c -> variant (1::Int) . h c
   lose f = CoArb $ absurd . f
 
 gcoarbitrary :: (ADT t, Constraints t CoArbitrary) => t -> Gen b -> Gen b
 gcoarbitrary = unCoArb $ consume (For :: For CoArbitrary) (CoArb coarbitrary)
+
+
+-- -- http://hackage.haskell.org/package/lens-4.3.3/docs/Generics-Deriving-Lens.html
+-- whenCastableOrElse :: forall a b f. (Typeable a, Typeable b) => (b -> f b) -> (a -> f a) -> a -> f a
+-- whenCastableOrElse f g = maybe g (\Refl -> f) (eqT :: Maybe (a :~: b))
+--
+-- tinplate :: forall t b. (Typeable b, Deep Typeable t) => Traversal' t b
+-- tinplate f
+--   | isAtom (Proxy :: Proxy t) = f `whenCastableOrElse` pure
+--   | otherwise = gtraverse (For :: For (Deep Typeable)) $ f `whenCastableOrElse` tinplate f
diff --git a/one-liner.cabal b/one-liner.cabal
--- a/one-liner.cabal
+++ b/one-liner.cabal
@@ -1,5 +1,5 @@
 Name:                 one-liner
-Version:              0.5.2
+Version:              0.6
 Synopsis:             Constraint-based generics
 Description:          Write short and concise generic instances of type classes.
                       .
@@ -27,17 +27,14 @@
 
   Exposed-modules:
     Generics.OneLiner
-    Generics.OneLiner.ADT
-    Generics.OneLiner.ADT1
-    Generics.OneLiner.Functions
-    Generics.OneLiner.Functions1
-    Generics.OneLiner.Info
+    Generics.OneLiner.Internal
 
   Build-depends:
-      base         >= 4.7 && < 5
-    , transformers >= 0.3 && < 0.6
-    , contravariant >= 1.2 && < 1.4
-    , ghc-prim
+      base          >= 4.9 && < 5
+    , transformers  >= 0.5 && < 0.6
+    , contravariant >= 1.4 && < 1.5
+    , ghc-prim      >= 0.5 && < 1.0
+    , profunctors   >= 5.2 && < 6.0
 
 source-repository head
   type:     git
diff --git a/src/Generics/OneLiner.hs b/src/Generics/OneLiner.hs
--- a/src/Generics/OneLiner.hs
+++ b/src/Generics/OneLiner.hs
@@ -13,17 +13,10 @@
 --
 -----------------------------------------------------------------------------
 {-# LANGUAGE
-    GADTs
-  , DataKinds
-  , RankNTypes
+    RankNTypes
   , TypeFamilies
-  , TypeOperators
   , ConstraintKinds
   , FlexibleContexts
-  , FlexibleInstances
-  , ScopedTypeVariables
-  , UndecidableInstances
-  , MultiParamTypeClasses
   #-}
 module Generics.OneLiner (
   -- * Producing values
@@ -36,181 +29,81 @@
   consume,
   -- * Single constructor functions
   op0, op1, op2,
+  -- * Generic programming with profunctors
+  GenericProfunctor(..), generic,
   -- * Types
-  ADT, ADTRecord, ADTNonEmpty, CtorCount, Constraints, For(..), Deep, DeepConstraint, isAtom
+  ADT, ADTRecord, ADTNonEmpty, CtorCount, Constraints, For(..)
 ) where
 
 import GHC.Generics
-import GHC.Prim (Constraint)
-import GHC.TypeLits
 import Control.Applicative
 import Data.Functor.Identity
-import Data.Monoid
-import Data.Proxy
-import Data.Typeable
 import Data.Functor.Contravariant
 import Data.Functor.Contravariant.Divisible
+import Data.Profunctor
+import Generics.OneLiner.Internal
 
-type family Constraints' (t :: * -> *) (c :: * -> Constraint) :: Constraint
-type instance Constraints' V1 c = ()
-type instance Constraints' U1 c = ()
-type instance Constraints' (f :+: g) c = (Constraints' f c, Constraints' g c)
-type instance Constraints' (f :*: g) c = (Constraints' f c, Constraints' g c)
-type instance Constraints' (K1 i v) c = c v
-type instance Constraints' (M1 i t f) c = Constraints' f c
 
-class ADT' (t :: * -> *) where
-  type CtorCount' t :: Nat
-  type CtorCount' t = 1
-  ctorIndex' :: t x -> Int
-  ctorIndex' _ = 0
-  ctorCount :: proxy t -> Int
-  ctorCount _ = 1
-  f0 :: (Constraints' t c, Applicative f)
-     => for c -> (forall s. c s => f s) -> [f (t ())]
-  f1 :: (Constraints' t c, Applicative f)
-     => for c -> (forall s. c s => s -> f s) -> t x -> f (t x)
-  f2 :: (Constraints' t c, Applicative f)
-     => for c -> (forall s. c s => s -> s -> f s) -> t x -> t x -> Maybe (f (t x))
-  c0 :: (Constraints' t c, Decidable f)
-     => for c -> (forall s. c s => f s) -> f (t ())
+newtype Zip f a b = Zip { runZip :: a -> a -> Maybe (f b) }
+instance Functor f => Profunctor (Zip f) where
+  dimap f g (Zip h) = Zip $ \a1 a2 -> fmap (fmap g) (h (f a1) (f a2))
+instance Applicative f => GenericProfunctor (Zip f) where
+  zero = Zip . const $ Just . pure
+  unit = Zip . const $ Just . pure
+  plus (Zip f) (Zip g) = Zip h where
+    h (L1 a) (L1 b) = fmap (fmap L1) (f a b)
+    h (R1 a) (R1 b) = fmap (fmap R1) (g a b)
+    h _ _ = Nothing
+  mult (Zip f) (Zip g) = Zip $ \(al :*: ar) (bl :*: br) -> liftA2 (:*:) <$> f al bl <*> g ar br
 
-instance ADT' V1 where
-  type CtorCount' V1 = 0
-  ctorCount _ = 0
-  f0 _ _ = []
-  f1 _ _ = pure
-  f2 _ _ _ = Just . pure
-  c0 _ _ = lose (\v -> v `seq` undefined)
+newtype Create f a b = Create { unCreate :: [f b] }
+instance Functor f => Profunctor (Create f) where
+  dimap _ f = Create . map (fmap f) . unCreate
+instance Applicative f => GenericProfunctor (Create f) where
+  zero = Create []
+  unit = Create [pure U1]
+  plus (Create l) (Create r) = Create $ map (fmap L1) l ++ map (fmap R1) r
+  mult (Create l) (Create r) = Create $ liftA2 (:*:) <$> l <*> r
 
-instance (ADT' f, ADT' g) => ADT' (f :+: g) where
-  type CtorCount' (f :+: g) = CtorCount' f + CtorCount' g
-  ctorIndex' (L1 l) = ctorIndex' l
-  ctorIndex' (R1 r) = ctorCount (Proxy :: Proxy f) + ctorIndex' r
-  ctorCount _ = ctorCount (Proxy :: Proxy f) + ctorCount (Proxy :: Proxy g)
-  f0 for f = map (fmap L1) (f0 for f) ++ map (fmap R1) (f0 for f)
-  f1 for f (L1 l) = L1 <$> f1 for f l
-  f1 for f (R1 r) = R1 <$> f1 for f r
-  f2 for f (L1 a) (L1 b) = fmap (fmap L1) (f2 for f a b)
-  f2 for f (R1 a) (R1 b) = fmap (fmap R1) (f2 for f a b)
-  f2 _ _ _ _ = Nothing
-  c0 for f = choose h (c0 for f) (c0 for f) where
+newtype Consume f a b = Consume { unConsume :: f a }
+instance Contravariant f => Profunctor (Consume f) where
+  dimap f _ = Consume . contramap f . unConsume
+instance Decidable f => GenericProfunctor (Consume f) where
+  zero = Consume $ lose (\v -> v `seq` undefined)
+  unit = Consume conquer
+  plus (Consume f) (Consume g) = Consume $ choose h f g where
     h (L1 l) = Left l
     h (R1 r) = Right r
+  mult (Consume f) (Consume g) = Consume $ divide (\(l :*: r) -> (l, r)) f g
 
-instance ADT' U1 where
-  f0 _ _ = [pure U1]
-  f1 _ _ = pure
-  f2 _ _ _ = Just . pure
-  c0 _ _ = conquer
 
-instance (ADT' f, ADT' g) => ADT' (f :*: g) where
-  f0 for f = [(:*:) <$> head (f0 for f) <*> head (f0 for f)]
-  f1 for f (l :*: r) = (:*:) <$> f1 for f l <*> f1 for f r
-  f2 for f (al :*: ar) (bl :*: br) = liftA2 (:*:) <$> f2 for f al bl <*> f2 for f ar br
-  c0 for f = divide (\(l :*: r) -> (l, r)) (c0 for f) (c0 for f)
-
-instance ADT' (K1 i v) where
-  f0 _ f = [K1 <$> f]
-  f1 _ f (K1 v) = K1 <$> f v
-  f2 _ f (K1 l) (K1 r) = Just $ K1 <$> f l r
-  c0 _ f = contramap unK1 f
-
-instance ADT' f => ADT' (M1 i t f) where
-  type CtorCount' (M1 i t f) = CtorCount' f
-  ctorIndex' = ctorIndex' . unM1
-  ctorCount _ = ctorCount (Proxy :: Proxy f)
-  f0 for f = map (fmap M1) (f0 for f)
-  f1 for f = fmap M1 . f1 for f . unM1
-  f2 for f (M1 l) (M1 r) = fmap (fmap M1) (f2 for f l r)
-  c0 for f = contramap unM1 (c0 for f)
-
--- | `Constraints` is a constraint type synonym, containing the constraint requirements for an instance for `t` of class `c`.
--- It requires an instance of class `c` for each component of `t`.
-type Constraints t c = Constraints' (Rep t) c
-
--- | `ADT` is a constraint type synonym. The `Generic` instance can be derived,
--- and any generic representation will be an instance of `ADT'`.
-type ADT t = (Generic t, ADT' (Rep t))
-
--- | `CtorCount` is the number of constructors of a type at the type level.
--- F.e. if you want to require that a type has at least two constructors,
--- you can add the constraint @(2 `GHC.TypeLits.<=` `CtorCount` t)@.
-type CtorCount t = CtorCount' (Rep t)
-
--- | `ADTRecord` is a constraint type synonym. An instance is an `ADT` with *exactly* one constructor.
-type ADTRecord t = (ADT t, 1 ~ CtorCount t)
-
--- | `ADTNonEmpty` is a constraint type synonym. An instance is an `ADT` with *at least* one constructor.
-type ADTNonEmpty t = (ADT t, 1 <= CtorCount t)
-
--- | Tell the compiler which class we want to use in the traversal. Should be used like this:
---
--- > (For :: For Show)
---
--- Where @Show@ can be any class.
-data For (c :: * -> Constraint) = For
-
--- | @Deep c@ recursively requires all parts of the datatype to be an instance of `c` and of `Generic`.
-class DeepConstraint c t => Deep (c :: * -> Constraint) t where
-instance DeepConstraint c t => Deep c t
-
--- http://stackoverflow.com/questions/14133121/can-i-constrain-a-type-family
--- | A trick to avoid GHC from detecting a cycle.
-type family DeepConstraint (c :: * -> Constraint) t :: Constraint
-type instance DeepConstraint c t = (c t, ADT t, Constraints t (Deep c), Constraints t c)
-
--- | For primitive values like `Int`, `Float`, `Double` and `Char`, the generic representation
--- of a value contains itself. If you use generics recursively (f.e. using `Deep`),
--- use `isAtom` to detect primitive values and prevent an infinite loop.
-isAtom :: forall t proxy. (ADT t, Typeable t, Constraints t Typeable) => proxy t -> Bool
-isAtom pt = case createA (For :: For Typeable) f :: [Const [Bool] t] of
-  [Const [True]] -> True
-  _ -> False
-  where
-    f :: forall a. Typeable a => Const [Bool] a
-    f = Const [tRep == typeRep (undefined :: [a])]
-    tRep = typeRep pt
-
 -- | Create a value (one for each constructor), given how to construct the components.
 --
 -- @
--- `minBound` = `head` `$` `create` (`For` :: `For` `Bounded`) `minBound`
--- `maxBound` = `last` `$` `create` (`For` :: `For` `Bounded`) `maxBound`
+-- `minBound` = `head` `$` `create` (`For` :: `For` `Bounded`) [`minBound`]
+-- `maxBound` = `last` `$` `create` (`For` :: `For` `Bounded`) [`maxBound`]
 -- @
 create :: (ADT t, Constraints t c)
-       => for c -> (forall s. c s => s) -> [t]
-create for f = map runIdentity (createA for (Identity f))
+       => for c -> (forall s. c s => [s]) -> [t]
+create for f = map runIdentity (createA for (Identity <$> f))
 
 -- | Create a value (one for each constructor), given how to construct the components, under an applicative effect.
 --
 -- Here's how to implement `get` from the `binary` package:
 --
 -- @
--- get = getWord8 `>>=` \\ix -> `createA` (`For` :: `For` Binary) get `!!` `fromEnum` ix
+-- get = getWord8 `>>=` \\ix -> `createA` (`For` :: `For` Binary) [get] `!!` `fromEnum` ix
 -- @
 createA :: (ADT t, Constraints t c, Applicative f)
-        => for c -> (forall s. c s => f s) -> [f t]
-createA for f = map (fmap to) (f0 for f)
+        => for c -> (forall s. c s => [f s]) -> [f t]
+createA for f = unCreate $ generic for (Create f)
 
 -- | Generate ways to consume values of type `t`. This is the contravariant version of `createA`.
 consume :: (ADT t, Constraints t c, Decidable f)
         => for c -> (forall s. c s => f s) -> f t
-consume for f = contramap from (c0 for f)
+consume for f = unConsume $ generic for (Consume f)
 
 
--- | Get the index in the lists returned by `create` and `createA` of the constructor of the given value.
---
--- For example, this is the implementation of `put` that generates the binary data that
--- the above implentation of `get` expects:
---
--- @
--- `put` t = `putWord8` (`toEnum` (`ctorIndex` t)) `<>` `gfoldMap` (`For` :: `For` `Binary`) `put` t
--- @
---
--- /Note that this assumes a straightforward `Monoid` instance of `Put` which `binary` unfortunately does not provide./
-ctorIndex :: ADT t => t -> Int
-ctorIndex = ctorIndex' . from
 
 -- | Map over a structure, updating each component.
 gmap :: (ADT t, Constraints t c)
@@ -231,13 +124,13 @@
 -- | Map each component of a structure to an action, evaluate these actions from left to right, and collect the results.
 gtraverse :: (ADT t, Constraints t c, Applicative f)
           => for c -> (forall s. c s => s -> f s) -> t -> f t
-gtraverse for f = fmap to . f1 for f . from
+gtraverse for f = runStar $ generic for (Star f)
 
 -- | Combine two values by combining each component of the structures with the given function.
 -- Returns `Nothing` if the constructors don't match.
 gzipWith :: (ADT t, Constraints t c)
-         => for c -> (forall s. c s => s -> s -> s) -> t -> t -> Maybe t
-gzipWith for f l r = runIdentity <$> zipWithA for (\x y -> Identity (f x y)) l r
+         => for c -> (forall s. c s => s -> s -> Maybe s) -> t -> t -> Maybe t
+gzipWith for f l r = runIdentity <$> zipWithA for (\x y -> Identity <$> f x y) l r
 
 -- | Combine two values by combining each component of the structures to a monoid, and combine the results.
 -- Returns `mempty` if the constructors don't match.
@@ -247,13 +140,13 @@
 -- @
 mzipWith :: (ADT t, Constraints t c, Monoid m)
          => for c -> (forall s. c s => s -> s -> m) -> t -> t -> m
-mzipWith for f l r = maybe mempty getConst $ zipWithA for (\x y -> Const (f x y)) l r
+mzipWith for f l r = maybe mempty getConst $ zipWithA for (\x y -> Just . Const $ f x y) l r
 
 -- | Combine two values by combining each component of the structures with the given function, under an applicative effect.
 -- Returns `Nothing` if the constructors don't match.
 zipWithA :: (ADT t, Constraints t c, Applicative f)
-         => for c -> (forall s. c s => s -> s -> f s) -> t -> t -> Maybe (f t)
-zipWithA for f l r = fmap (fmap to) (f2 for f (from l) (from r))
+         => for c -> (forall s. c s => s -> s -> Maybe (f s)) -> t -> t -> Maybe (f t)
+zipWithA for f = runZip $ generic for (Zip f)
 
 -- | Implement a nullary operator by calling the operator for each component.
 --
@@ -263,7 +156,7 @@
 -- @
 op0 :: (ADTRecord t, Constraints t c)
     => for c -> (forall s. c s => s) -> t
-op0 for f = head $ create for f
+op0 for f = head $ create for [f]
 
 -- | Implement a unary operator by calling the operator on the components.
 -- This is here for consistency, it is the same as `gmap`.
@@ -283,6 +176,6 @@
 -- @
 op2 :: (ADTRecord t, Constraints t c)
     => for c -> (forall s. c s => s -> s -> s) -> t -> t -> t
-op2 for f l r = case gzipWith for f l r of
+op2 for f l r = case gzipWith for (\a b -> Just (f a b)) l r of
   Just t -> t
   Nothing -> error "op2: constructor mismatch should not be possible for ADTRecord"
diff --git a/src/Generics/OneLiner/ADT.hs b/src/Generics/OneLiner/ADT.hs
deleted file mode 100644
--- a/src/Generics/OneLiner/ADT.hs
+++ /dev/null
@@ -1,288 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Generics.OneLiner.ADT
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  sjoerd@w3future.com
--- Stability   :  experimental
--- Portability :  non-portable
---
--- This module is for writing generic functions on algebraic data types
--- of kind @*@. These data types must be an instance of the `ADT` type class.
---
--- Here's an example how to write such an instance for this data type:
---
--- @
--- data T a = A Int a | B a (T a)
--- @
---
--- @
--- instance `ADT` (T a) where
---   `ctorIndex` A{} = 0
---   `ctorIndex` B{} = 1
---   `ctorInfo` _ 0 = `ctor` \"A\"
---   `ctorInfo` _ 1 = `ctor` \"B\"
---   type `Constraints` (T a) c = (c Int, c a, c (T a))
---   `buildsRecA` _ sub rec =
---     [ A `<$>` sub (`FieldInfo` (\\(A i _) -> i)) `<*>` sub (`FieldInfo` (\\(A _ a) -> a))
---     , B `<$>` sub (`FieldInfo` (\\(B a _) -> a)) `<*>` rec (`FieldInfo` (\\(B _ t) -> t))
---     ]
--- @
---
--- And this is how you would write generic equality, using the `All` monoid:
---
--- @
--- eqADT :: (`ADT` t, `Constraints` t `Eq`) => t -> t -> `Bool`
--- eqADT s t = `ctorIndex` s == `ctorIndex` t `&&`
---   `getAll` (`mbuilds` (`For` :: `For` `Eq`) (\\fld -> `All` $ s `!` fld `==` t `!` fld) \``at`\` s)
--- @
------------------------------------------------------------------------------
-{-# LANGUAGE
-    RankNTypes
-  , TypeFamilies
-  , ConstraintKinds
-  , FlexibleInstances
-  , DefaultSignatures
-  , ScopedTypeVariables
-  #-}
-module Generics.OneLiner.ADT (
-
-    -- * Re-exports
-    module Generics.OneLiner.Info
-  , Constraint
-    -- | The kind of constraints
-
-    -- * The @ADT@ type class
-  , ADT(..)
-  , ADTRecord(..)
-  , For(..)
-
-    -- * Helper functions
-  , (!)
-  , at
-
-    -- * Derived traversal schemes
-  , builds
-  , mbuilds
-  , gmap
-  , gfoldMap
-  , gtraverse
-
-    -- ** ...for single constructor data types
-  , build
-  , op0
-  , op1
-  , op2
-
-  ) where
-
-import Generics.OneLiner.Info
-
-import GHC.Prim (Constraint)
-import Control.Applicative
-import Data.Functor.Identity
-import Data.Functor.Constant
-import Data.Monoid
-
-import Data.Maybe (fromJust)
-
-
--- | Tell the compiler which class we want to use in the traversal. Should be used like this:
---
--- > (For :: For Show)
---
--- Where @Show@ can be any class.
-data For (c :: * -> Constraint) = For
-
--- | Type class for algebraic data types of kind @*@. Implement either `buildsA`
--- if the type @t@ is not recursive, or `buildsRecA` if the type @t@ is recursive.
-class ADT t where
-
-  -- | Gives the index of the constructor of the given value in the list returned by `buildsA` and `buildsRecA`.
-  ctorIndex :: t -> Int
-  ctorIndex _ = 0
-
-  -- | @ctorInfo n@ gives constructor information, f.e. its name, for the @n@th constructor.
-  --   The first argument is a dummy argument and can be @(undefined :: t)@.
-  ctorInfo :: t -> Int -> CtorInfo
-
-  -- | The constraints needed to run `buildsA` and `buildsRecA`.
-  -- It should be a list of all the types of the subcomponents of @t@, each applied to @c@.
-  type Constraints t (c :: * -> Constraint) :: Constraint
-
-  buildsA :: (Constraints t c, Applicative f)
-          => for c -- ^ Witness for the constraint @c@.
-          -> (forall s. c s => FieldInfo (t -> s) -> f s) -- ^ This function should return a value
-             -- for each subcomponent of @t@, wrapped in an applicative functor @f@. It is given
-             -- information about the field, which contains a projector function to get the subcomponent
-             -- from a value of type @t@. The type of the subcomponent is an instance of class @c@.
-          -> [f t] -- ^ A list of results, one for each constructor of type @t@. Each element is the
-             -- result of applicatively applying the constructor to the results of the given function
-             -- for each field of the constructor.
-
-  default buildsA :: (c t, Constraints t c, Applicative f)
-                  => for c -> (forall s. c s => FieldInfo (t -> s) -> f s) -> [f t]
-  buildsA for f = buildsRecA for f f
-
-  buildsRecA :: (Constraints t c, Applicative f)
-             => for c -- ^ Witness for the constraint @c@.
-             -> (forall s. c s => FieldInfo (t -> s) -> f s) -- ^ This function should return a value
-                -- for each subcomponent of @t@, wrapped in an applicative functor @f@. It is given
-                -- information about the field, which contains a projector function to get the subcomponent
-                -- from a value of type @t@. The type of the subcomponent is an instance of class @c@.
-             -> (FieldInfo (t -> t) -> f t) -- ^ This function should return a value
-                -- for each subcomponent of @t@ that is itself of type @t@.
-             -> [f t] -- ^ A list of results, one for each constructor of type @t@. Each element is the
-             -- result of applicatively applying the constructor to the results of the given function
-             -- for each field of the constructor.
-  buildsRecA for sub _ = buildsA for sub
-
-  {-# MINIMAL ctorInfo, (buildsA | buildsRecA) #-}
-
--- | Add an instance for this class if the data type has exactly one constructor.
---
---   This class has no methods.
-class ADT t => ADTRecord t where
-
--- | `buildsA` specialized to the `Identity` applicative functor.
-builds :: (ADT t, Constraints t c)
-       => for c -> (forall s. c s => FieldInfo (t -> s) -> s) -> [t]
-builds for f = runIdentity <$> buildsA for (Identity . f)
-
--- | `buildsA` specialized to the `Constant` applicative functor, which collects monoid values @m@.
-mbuilds :: forall t c m for. (ADT t, Constraints t c, Monoid m)
-        => for c -> (forall s. c s => FieldInfo (t -> s) -> m) -> [m]
-mbuilds for f = getConstant <$> (buildsA for (Constant . f) :: [Constant m t])
-
--- | Transform a value by transforming each subcomponent.
-gmap :: (ADT t, Constraints t c)
-     => for c -> (forall s. c s => s -> s) -> t -> t
-gmap for f t = builds for (\fld -> f (t ! fld)) `at` t
-
--- | Fold a value, by mapping each subcomponent to a monoid value and collecting those.
-gfoldMap :: (ADT t, Constraints t c, Monoid m)
-         => for c -> (forall s. c s => s -> m) -> t -> m
-gfoldMap for f = getConstant . gtraverse for (Constant . f)
-
--- | Applicative traversal given a way to traverse each subcomponent.
-gtraverse :: (ADT t, Constraints t c, Applicative f)
-          => for c -> (forall s. c s => s -> f s) -> t -> f t
-gtraverse for f t = buildsA for (\fld -> f (t ! fld)) `at` t
-
--- | `builds` for data types with exactly one constructor
-build :: (ADTRecord t, Constraints t c)
-      => for c -> (forall s. c s => FieldInfo (t -> s) -> s) -> t
-build for f = head $ builds for f
-
--- | Derive a 0-ary operation by applying the operation to every subcomponent.
-op0 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s) -> t
-op0 for op = build for (const op)
-
--- | Derive a unary operation by applying the operation to every subcomponent.
-op1 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s -> s) -> t -> t
-op1 for op t = build for (\fld -> op $ t ! fld)
-
--- | Derive a binary operation by applying the operation to every subcomponent.
-op2 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s -> s -> s) -> t -> t -> t
-op2 for op s t = build for (\fld -> (s ! fld) `op` (t ! fld))
-
-
-
-
-infixl 9 !
--- | Get the subcomponent by using the projector from the field information.
-(!) :: t -> FieldInfo (t -> s) -> s
-t ! fld = project fld t
-
--- | Get the value from the result of one of the @builds@ functions that matches the constructor of @t@.
-at :: ADT t => [a] -> t -> a
-at as t = as !! ctorIndex t
-
-
-
-instance ADT () where
-
-  type Constraints () c = ()
-  ctorInfo _ 0 = ctor "()"
-  buildsA _ _ = [ pure () ]
-
-instance ADTRecord () where
-
-instance ADT (a, b) where
-
-  type Constraints (a, b) c = (c a, c b)
-  ctorInfo _ 0 = ctor "(,)"
-  buildsA _ f = [ (,) <$> f (FieldInfo fst) <*> f (FieldInfo snd) ]
-
-instance ADTRecord (a, b) where
-
-instance ADT (a, b, c) where
-
-  type Constraints (a, b, c) tc = (tc a, tc b, tc c)
-  ctorInfo _ 0 = ctor "(,,)"
-  buildsA _ f = [(,,) <$> f (FieldInfo (\(a, _, _) -> a))
-                      <*> f (FieldInfo (\(_, b, _) -> b))
-                      <*> f (FieldInfo (\(_, _, c) -> c))
-                ]
-
-instance ADTRecord (a, b, c) where
-
-instance ADT (a, b, c, d) where
-
-  type Constraints (a, b, c, d) tc = (tc a, tc b, tc c, tc d)
-  ctorInfo _ 0 = ctor "(,,,)"
-  buildsA _ f = [(,,,) <$> f (FieldInfo (\(a, _, _, _) -> a))
-                       <*> f (FieldInfo (\(_, b, _, _) -> b))
-                       <*> f (FieldInfo (\(_, _, c, _) -> c))
-                       <*> f (FieldInfo (\(_, _, _, d) -> d))
-                ]
-
-instance ADTRecord (a, b, c, d) where
-
-instance ADT Bool where
-
-  ctorIndex False = 0
-  ctorIndex True  = 1
-  ctorInfo _ 0 = ctor "False"
-  ctorInfo _ 1 = ctor "True"
-
-  type Constraints Bool c = ()
-  buildsA for _ = [ pure False, pure True ]
-
-instance ADT (Either a b) where
-
-  ctorIndex Left{}  = 0
-  ctorIndex Right{} = 1
-  ctorInfo _ 0 = ctor "Left"
-  ctorInfo _ 1 = ctor "Right"
-
-  type Constraints (Either a b) c = (c a, c b)
-  buildsA for f =
-    [ Left  <$> f (FieldInfo (\(Left a)  -> a))
-    , Right <$> f (FieldInfo (\(Right a) -> a))
-    ]
-
-instance ADT (Maybe a) where
-
-  ctorIndex Nothing = 0
-  ctorIndex Just{}  = 1
-  ctorInfo _ 0 = ctor "Nothing"
-  ctorInfo _ 1 = ctor "Just"
-
-  type Constraints (Maybe a) c = c a
-  buildsA for f =
-    [ pure Nothing
-    , Just <$> f (FieldInfo fromJust)
-    ]
-
-instance ADT [a] where
-
-  ctorIndex []    = 0
-  ctorIndex (_:_) = 1
-  ctorInfo _ 0 = ctor "[]"
-  ctorInfo _ 1 = CtorInfo ":" False (Infix RightAssociative 5)
-
-  type Constraints [a] c = (c a, c [a])
-  buildsRecA for sub rec =
-    [ pure []
-    , (:) <$> sub (FieldInfo head) <*> rec (FieldInfo tail)]
diff --git a/src/Generics/OneLiner/ADT1.hs b/src/Generics/OneLiner/ADT1.hs
deleted file mode 100644
--- a/src/Generics/OneLiner/ADT1.hs
+++ /dev/null
@@ -1,202 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Generics.OneLiner.ADT1
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  sjoerd@w3future.com
--- Stability   :  experimental
--- Portability :  non-portable
---
--- This module is for writing generic functions on algebraic data types
--- of kind @* -> *@.
--- These data types must be an instance of the `ADT1` type class.
---
--- Here's an example how to write such an instance for this data type:
---
--- @
--- data T a = A [a] | B a (T a)
--- @
---
--- @
--- instance `ADT1` T where
---   `ctorIndex` A{} = 0
---   `ctorIndex` B{} = 1
---   `ctorInfo` _ 0 = `ctor` \"A\"
---   `ctorInfo` _ 1 = `ctor` \"B\"
---   type `Constraints` T c = (c [], c T)
---   `buildsRecA` _ par sub rec =
---     [ A `<$>` sub (`component` (\\(A l) -> l)
---     , B `<$>` par (`param` (\\(B a _) -> a)) `<*>` rec (`component` (\\(B _ t) -> t))
---     ]
--- @
------------------------------------------------------------------------------
-{-# LANGUAGE
-    RankNTypes
-  , TypeFamilies
-  , TypeOperators
-  , ConstraintKinds
-  , FlexibleInstances
-  , DefaultSignatures
-  , ScopedTypeVariables
-  #-}
-module Generics.OneLiner.ADT1 (
-
-    -- * Re-exports
-    module Generics.OneLiner.Info
-  , Constraint
-    -- | The kind of constraints
-
-    -- * The @ADT1@ type class
-  , ADT1(..)
-  , ADT1Record(..)
-  , For(..)
-  , Extract(..)
-  , (:~>)(..)
-
-    -- * Helper functions
-  , (!)
-  , (!~)
-  , at
-  , param
-  , component
-
-  -- * Derived traversal schemes
-  , builds
-  , mbuilds
-  , build
-
-  ) where
-
-import Generics.OneLiner.Info
-
-import GHC.Prim (Constraint)
-import Control.Applicative
-import Data.Functor.Identity
-import Data.Functor.Constant
-import Data.Monoid
-
-import Data.Maybe (fromJust)
-
-
-newtype f :~> g = Nat { getNat :: forall x. f x -> g x }
-newtype Extract f = Extract { getExtract :: forall x. f x -> x }
-
-
--- | Tell the compiler which class we want to use in the traversal. Should be used like this:
---
--- > (For :: For Show)
---
--- Where @Show@ can be any class.
-data For (c :: (* -> *) -> Constraint) = For
-
--- | Type class for algebraic data types of kind @* -> *@. Implement either `buildsA`
--- if the type @t@ is not recursive, or `buildsRecA` if the type @t@ is recursive.
-class ADT1 t where
-
-  -- | Gives the index of the constructor of the given value in the list returned by `buildsA` and `buildsRecA`.
-  ctorIndex :: t a -> Int
-  ctorIndex _ = 0
-
-  -- | @ctorInfo n@ gives constructor information, f.e. its name, for the @n@th constructor.
-  --   The first argument is a dummy argument and can be @(undefined :: t a)@.
-  ctorInfo :: t a -> Int -> CtorInfo
-
-  -- | The constraints needed to run `buildsA` and `buildsRecA`.
-  -- It should be a list of all the types of the subcomponents of @t@, each applied to @c@.
-  type Constraints t (c :: (* -> *) -> Constraint) :: Constraint
-  buildsA :: (Constraints t c, Applicative f)
-          => for c -- ^ Witness for the constraint @c@.
-          -> (FieldInfo (Extract t) -> f b)
-          -> (forall s. c s => FieldInfo (t :~> s) -> f (s b))
-          -> [f (t b)]
-
-  default buildsA :: (c t, Constraints t c, Applicative f)
-                  => for c
-                  -> (FieldInfo (Extract t) -> f b)
-                  -> (forall s. c s => FieldInfo (t :~> s) -> f (s b))
-                  -> [f (t b)]
-  buildsA for param sub = buildsRecA for param sub sub
-
-  buildsRecA :: (Constraints t c, Applicative f)
-             => for c -- ^ Witness for the constraint @c@.
-             -> (FieldInfo (Extract t) -> f b)
-             -> (forall s. c s => FieldInfo (t :~> s) -> f (s b))
-             -> (FieldInfo (t :~> t) -> f (t b))
-             -> [f (t b)]
-  buildsRecA for param sub _ = buildsA for param sub
-
-  {-# MINIMAL ctorInfo, (buildsA | buildsRecA) #-}
-
--- | Add an instance for this class if the data type has exactly one constructor.
---
---   This class has no methods.
-class ADT1 t => ADT1Record t where
-
--- | `buildsA` specialized to the `Identity` applicative functor.
-builds :: (ADT1 t, Constraints t c)
-       => for c
-       -> (FieldInfo (Extract t) -> b)
-       -> (forall s. c s => FieldInfo (t :~> s) -> s b)
-       -> [t b]
-builds for f g = runIdentity <$> buildsA for (Identity . f) (Identity . g)
-
--- | `buildsA` specialized to the `Constant` applicative functor, which collects monoid values @m@.
-mbuilds :: forall t c m for. (ADT1 t, Constraints t c, Monoid m)
-        => for c
-        -> (FieldInfo (Extract t) -> m)
-        -> (forall s. c s => FieldInfo (t :~> s) -> m)
-        -> [m]
-mbuilds for f g = getConstant <$> (buildsA for (Constant . f) (Constant . g) :: [Constant m (t b)])
-
--- | `builds` for data types with exactly one constructor
-build :: (ADT1Record t, Constraints t c)
-       => for c
-       -> (FieldInfo (Extract t) -> b)
-       -> (forall s. c s => FieldInfo (t :~> s) -> s b)
-       -> t b
-build for f g = head $ builds for f g
-
--- | Get the value from the result of one of the @builds@ functions that matches the constructor of @t@.
-at :: ADT1 t => [a] -> t b -> a
-at as t = as !! ctorIndex t
-
-param :: (forall a. t a -> a) -> FieldInfo (Extract t)
-param f = FieldInfo (Extract f)
-
-component :: (forall a. t a -> s a) -> FieldInfo (t :~> s)
-component f = FieldInfo (Nat f)
-
-infixl 9 !
-(!) :: t a -> FieldInfo (Extract t) -> a
-t ! info = getExtract (project info) t
-
-infixl 9 !~
-(!~) :: t a -> FieldInfo (t :~> s) -> s a
-t !~ info = getNat (project info) t
-
-
-instance ADT1 Maybe where
-
-  ctorIndex Nothing = 0
-  ctorIndex Just{}  = 1
-  ctorInfo _ 0 = ctor "Nothing"
-  ctorInfo _ 1 = ctor "Just"
-
-  type Constraints Maybe c = ()
-  buildsA _ f _ =
-    [ pure Nothing
-    , Just <$> f (param fromJust)
-    ]
-
-instance ADT1 [] where
-
-  ctorIndex []    = 0
-  ctorIndex (_:_) = 1
-  ctorInfo _ 0 = ctor "[]"
-  ctorInfo _ 1 = CtorInfo ":" False (Infix RightAssociative 5)
-
-  type Constraints [] c = c []
-  buildsRecA _ p _ r =
-    [ pure []
-    , (:) <$> p (param head) <*> r (component tail)
-    ]
diff --git a/src/Generics/OneLiner/Functions.hs b/src/Generics/OneLiner/Functions.hs
deleted file mode 100644
--- a/src/Generics/OneLiner/Functions.hs
+++ /dev/null
@@ -1,114 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Generics.OneLiner.Functions
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  sjoerd@w3future.com
--- Stability   :  experimental
--- Portability :  non-portable
------------------------------------------------------------------------------
-{-# LANGUAGE RankNTypes, ConstraintKinds, ScopedTypeVariables #-}
-module Generics.OneLiner.Functions (
-  -- * For all instances
-    eqADT
-  , compareADT
-  , minBoundADT
-  , maxBoundADT
-  , showsPrecADT
-  , readPrecADT
-  -- * For datatypes with one constructor
-  , memptyADT
-  , mappendADT
-  , fromIntegerADT
-  ) where
-
-import Generics.OneLiner.ADT
-import Control.Applicative
-import Data.Monoid
-
-import Text.Read
-import Control.Monad
-import Control.Monad.Trans.State
-import qualified Control.Monad.Trans.Class as T
-
-eqADT :: (ADT t, Constraints t Eq) => t -> t -> Bool
-eqADT s t = ctorIndex s == ctorIndex t &&
-  getAll (mbuilds (For :: For Eq) (\fld -> All $ s ! fld == t ! fld) `at` s)
-
-compareADT :: (ADT t, Constraints t Ord) => t -> t -> Ordering
-compareADT s t = compare (ctorIndex s) (ctorIndex t) <>
-  mbuilds (For :: For Ord) (\fld -> compare (s ! fld) (t ! fld)) `at` s
-
-minBoundADT :: (ADT t, Constraints t Bounded) => t
-minBoundADT = head $ builds (For :: For Bounded) (const minBound)
-
-maxBoundADT :: (ADT t, Constraints t Bounded) => t
-maxBoundADT = last $ builds (For :: For Bounded) (const maxBound)
-
-showsPrecADT :: forall t. (ADT t, Constraints t Show) => Int -> t -> ShowS
-showsPrecADT d t = inner fty
-  where
-    CtorInfo name rec fty = ctorInfo t (ctorIndex t)
-
-    inner (Infix _ d') = showParen (d > d') $ let [f0, f1] = fields (d' + 1) in
-      f0 . showChar ' ' . showString name . showChar ' ' . f1
-    inner _ = showParen (d > 10) $ showString name . showChar ' ' . body
-
-    body = if rec
-      then showChar '{' . conc (showString ", ") (fields 0) . showChar '}'
-      else conc (showString " ") (fields 11)
-
-    fields d' = mbuilds (For :: For Show) (return . f d') `at` t
-
-    f :: Show s => Int -> FieldInfo (t -> s) -> ShowS
-    f d' info = if rec
-      then showString (selectorName info) . showString " = " . showsPrec d' (t ! info)
-      else showsPrec d' (t ! info)
-
-    conc sep = foldr1 (\g ss -> g . sep . ss)
-
-readPrecADT :: forall t. (ADT t, Constraints t Read) => ReadPrec t
-readPrecADT = parens (choice ctorReads)
-  where
-    ctorReads = ctorParse <$> zip (fmap (ctorInfo (undefined :: t)) [0..]) (buildsA (For :: For Read) fieldParse)
-
-    ctorParse (CtorInfo name _ (Infix _ d), getFields) =
-      let flds = evalStateT getFields $ do { Symbol name' <- lexP; guard (name' == name) }
-      in prec d flds
-
-    ctorParse (CtorInfo name rec _, getFields) =
-      let flds = evalStateT getFields (return ())
-      in prec (if rec then 11 else 10) $ do
-        Ident name' <- lexP
-        guard (name == name')
-        if rec then do
-            Punc "{" <- lexP
-            res <- flds
-            Punc "}" <- lexP
-            return res
-          else
-            flds
-
-    -- StateT is used to parse an infix operator after the first field
-    fieldParse :: Read s => FieldInfo (t -> s) -> StateT (ReadPrec ()) ReadPrec s
-    fieldParse (SelectorInfo name _) = StateT $ \parseOp -> do
-      Ident name' <- lexP
-      guard (name == name')
-      Punc "=" <- lexP
-      res <- reset readPrec
-      parseOp
-      return (res, return ())
-    fieldParse _ = StateT $ \parseOp -> do
-      res <- step readPrec
-      parseOp
-      return (res, return ())
-
-
-memptyADT :: (ADTRecord t, Constraints t Monoid) => t
-memptyADT = op0 (For :: For Monoid) mempty
-
-mappendADT :: (ADTRecord t, Constraints t Monoid) => t -> t -> t
-mappendADT = op2 (For :: For Monoid) mappend
-
-fromIntegerADT :: (ADTRecord t, Constraints t Num) => Integer -> t
-fromIntegerADT i = op0 (For :: For Num) (fromInteger i)
diff --git a/src/Generics/OneLiner/Functions1.hs b/src/Generics/OneLiner/Functions1.hs
deleted file mode 100644
--- a/src/Generics/OneLiner/Functions1.hs
+++ /dev/null
@@ -1,52 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Generics.OneLiner.Functions1
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  sjoerd@w3future.com
--- Stability   :  experimental
--- Portability :  non-portable
------------------------------------------------------------------------------
-{-# LANGUAGE RankNTypes, ConstraintKinds, ScopedTypeVariables #-}
-module Generics.OneLiner.Functions1 (
-  -- * For all instances
-    fmapADT
-  , foldMapADT
-  , traverseADT
-  -- * For datatypes with one constructor
-  , pureADT
-  , apADT
-  , bindADT
-  , mfixADT
-) where
-
-import Generics.OneLiner.ADT1
-import Control.Applicative
-import Control.Monad.Fix
-import Data.Monoid
-import Data.Foldable
-import Data.Traversable
-
-fmapADT :: (ADT1 t, Constraints t Functor) => (a -> b) -> t a -> t b
-fmapADT f ta = builds (For :: For Functor) (\fld -> f (ta ! fld)) (\fld -> fmap f (ta !~ fld)) `at` ta
-
-foldMapADT :: (ADT1 t, Constraints t Foldable, Monoid m) => (a -> m) -> t a -> m
-foldMapADT f ta = mbuilds (For :: For Foldable) (\fld -> f (ta ! fld)) (\fld -> foldMap f (ta !~ fld)) `at` ta
-
-traverseADT :: (ADT1 t, Constraints t Traversable, Applicative f) => (a -> f b) -> t a -> f (t b)
-traverseADT f ta = buildsA (For :: For Traversable) (\fld -> f (ta ! fld)) (\fld -> traverse f (ta !~ fld)) `at` ta
-
--- unfoldADT :: (ADT1 t, Constraints t Unfoldable, Unfolder f) => f a -> f (t a)
--- unfoldADT fa = choose $ buildsA (For :: For Unfoldable) (const fa) (const $ unfold fa)
-
-pureADT :: (ADT1Record t, Constraints t Applicative) => a -> t a
-pureADT a = build (For :: For Applicative) (const a) (const $ pure a)
-
-apADT :: (ADT1Record t, Constraints t Applicative) => t (a -> b) -> t a -> t b
-apADT tf ta = build (For :: For Applicative) (\fld -> (tf ! fld) (ta ! fld)) (\fld -> (tf !~ fld) <*> (ta !~ fld))
-
-bindADT :: (ADT1Record t, Constraints t Monad) => t a -> (a -> t b) -> t b
-bindADT ta f = build (For :: For Monad) (\fld -> f (ta ! fld) ! fld) (\fld -> (ta !~ fld) >>= ((!~ fld) . f))
-
-mfixADT :: (ADT1Record t, Constraints t MonadFix) => (a -> t a) -> t a
-mfixADT f = build (For :: For MonadFix) (\fld -> fix ((! fld) . f)) (\fld -> mfix ((!~ fld) . f))
diff --git a/src/Generics/OneLiner/Info.hs b/src/Generics/OneLiner/Info.hs
deleted file mode 100644
--- a/src/Generics/OneLiner/Info.hs
+++ /dev/null
@@ -1,39 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Generics.OneLiner.Info
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  sjoerd@w3future.com
--- Stability   :  experimental
--- Portability :  non-portable
------------------------------------------------------------------------------
-module Generics.OneLiner.Info where
-
-data CtorInfo = CtorInfo
-  { ctorName  :: String
-  , isRecord  :: Bool
-  , fixity    :: Fixity
-  }
-  deriving (Eq, Show, Ord, Read)
-
-ctor :: String -> CtorInfo
-ctor name = CtorInfo name False Prefix
-
-data Fixity = Prefix | Infix Associativity Int
-  deriving (Eq, Show, Ord, Read)
-
-data Associativity = LeftAssociative | RightAssociative | NotAssociative
-  deriving (Eq, Show, Ord, Read)
-
-data FieldInfo p
-  = SelectorInfo
-    { selectorName :: String
-    , project      :: p
-    }
-  | FieldInfo
-    { project      :: p
-    }
-
-instance Functor FieldInfo where
-  fmap f (SelectorInfo s p) = SelectorInfo s (f p)
-  fmap f (FieldInfo p) = FieldInfo (f p)
diff --git a/src/Generics/OneLiner/Internal.hs b/src/Generics/OneLiner/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Generics/OneLiner/Internal.hs
@@ -0,0 +1,133 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Generics.OneLiner.Internal
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  sjoerd@w3future.com
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-----------------------------------------------------------------------------
+{-# LANGUAGE
+    GADTs
+  , DataKinds
+  , RankNTypes
+  , LambdaCase
+  , TypeFamilies
+  , TypeOperators
+  , ConstraintKinds
+  , FlexibleContexts
+  , ScopedTypeVariables
+  , UndecidableInstances
+  #-}
+module Generics.OneLiner.Internal where
+
+import GHC.Generics
+import GHC.Types (Constraint)
+import GHC.TypeLits
+import Data.Proxy
+import Data.Profunctor
+
+type family Constraints' (t :: * -> *) (c :: * -> Constraint) :: Constraint
+type instance Constraints' V1 c = ()
+type instance Constraints' U1 c = ()
+type instance Constraints' (f :+: g) c = (Constraints' f c, Constraints' g c)
+type instance Constraints' (f :*: g) c = (Constraints' f c, Constraints' g c)
+type instance Constraints' (M1 i t f) c = Constraints' f c
+type instance Constraints' (K1 i a) c = c a
+
+class ADT' (t :: * -> *) where
+  type CtorCount' t :: Nat
+  type CtorCount' t = 1
+  ctorIndex' :: t x -> Int
+  ctorIndex' _ = 0
+  ctorCount :: proxy t -> Int
+  ctorCount _ = 1
+
+  p :: (Constraints' t c, GenericProfunctor p)
+    => for c -> (forall s. c s => p s s) -> p (t x) (t x)
+
+instance ADT' V1 where
+  type CtorCount' V1 = 0
+  ctorCount _ = 0
+  p _ _ = zero
+
+instance (ADT' f, ADT' g) => ADT' (f :+: g) where
+  type CtorCount' (f :+: g) = CtorCount' f + CtorCount' g
+  ctorIndex' (L1 l) = ctorIndex' l
+  ctorIndex' (R1 r) = ctorCount (Proxy :: Proxy f) + ctorIndex' r
+  ctorCount _ = ctorCount (Proxy :: Proxy f) + ctorCount (Proxy :: Proxy g)
+  p for f = plus (p for f) (p for f)
+
+instance ADT' U1 where
+  p _ _ = unit
+
+instance (ADT' f, ADT' g) => ADT' (f :*: g) where
+  p for f = mult (p for f) (p for f)
+
+instance ADT' (K1 i v) where
+  p _ = dimap unK1 K1
+
+instance ADT' f => ADT' (M1 i t f) where
+  type CtorCount' (M1 i t f) = CtorCount' f
+  ctorIndex' = ctorIndex' . unM1
+  ctorCount _ = ctorCount (Proxy :: Proxy f)
+  p for f = dimap unM1 M1 (p for f)
+
+
+class Profunctor p => GenericProfunctor p where
+  zero :: p (V1 a) (V1 a)
+  unit :: p (U1 a) (U1 a)
+  plus :: p (f a) (f' a) -> p (g a) (g' a) -> p ((f :+: g) a) ((f' :+: g') a)
+  mult :: p (f a) (f' a) -> p (g a) (g' a) -> p ((f :*: g) a) ((f' :*: g') a)
+
+instance Applicative f => GenericProfunctor (Star f) where
+  zero = Star pure
+  unit = Star pure
+  plus (Star f) (Star g) = Star $ \case
+    L1 l -> L1 <$> f l
+    R1 r -> R1 <$> g r
+  mult (Star f) (Star g) = Star $ \(l :*: r) -> (:*:) <$> f l <*> g r
+
+-- | All the above functions have been implemented using this single function,
+-- using different `profunctor`s.
+generic :: (ADT t, Constraints t c, GenericProfunctor p)
+        => for c -> (forall s. c s => p s s) -> p t t
+generic for f = dimap from to $ p for f
+
+-- | `Constraints` is a constraint type synonym, containing the constraint requirements for an instance for `t` of class `c`.
+-- It requires an instance of class `c` for each component of `t`.
+type Constraints t c = Constraints' (Rep t) c
+
+-- | `ADT` is a constraint type synonym. The `Generic` instance can be derived,
+-- and any generic representation will be an instance of `ADT'`.
+type ADT t = (Generic t, ADT' (Rep t))
+
+-- | `CtorCount` is the number of constructors of a type at the type level.
+-- F.e. if you want to require that a type has at least two constructors,
+-- you can add the constraint @(2 `GHC.TypeLits.<=` `CtorCount` t)@.
+type CtorCount t = CtorCount' (Rep t)
+
+-- | `ADTRecord` is a constraint type synonym. An instance is an `ADT` with *exactly* one constructor.
+type ADTRecord t = (ADT t, 1 ~ CtorCount t)
+
+-- | `ADTNonEmpty` is a constraint type synonym. An instance is an `ADT` with *at least* one constructor.
+type ADTNonEmpty t = (ADT t, 1 <= CtorCount t)
+
+-- | Tell the compiler which class we want to use in the traversal. Should be used like this:
+--
+-- > (For :: For Show)
+--
+-- Where @Show@ can be any class.
+data For (c :: * -> Constraint) = For
+
+-- | Get the index in the lists returned by `create` and `createA` of the constructor of the given value.
+--
+-- For example, this is the implementation of `put` that generates the binary data that
+-- the above implentation of `get` expects:
+--
+-- @
+-- `put` t = `putWord8` (`toEnum` (`ctorIndex` t)) `<>` `gfoldMap` (`For` :: `For` `Binary`) `put` t
+-- @
+ctorIndex :: ADT t => t -> Int
+ctorIndex = ctorIndex' . from
