diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Hardy Jones
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
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/hinquire.cabal b/hinquire.cabal
new file mode 100644
--- /dev/null
+++ b/hinquire.cabal
@@ -0,0 +1,46 @@
+-- Initial hinquire.cabal generated by cabal init.  For further
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                hinquire
+version:             0.1.0.0
+synopsis:            Generate armet style query strings.
+description:         Hinquire is a formalization/testing bed for inquire.js
+homepage:            https://github.com/joneshf/hinquire
+license:             MIT
+license-file:        LICENSE
+author:              Hardy Jones
+maintainer:          jones3.hardy@gmail.com
+-- copyright:
+category:            Network
+build-type:          Simple
+-- extra-source-files:
+cabal-version:       >=1.10
+
+source-repository head
+  type:     git
+  location: git://github.com/joneshf/hinquire.git
+
+library
+  exposed-modules:     Network.Hinquire
+  build-depends:       base >=4.6 && <4.7,
+                       bifunctors >= 4.1.1 && <5.0,
+                       QuickCheck >= 2.6 && <3.0,
+                       test-framework >=0.8.0,
+                       test-framework-quickcheck2 >=0.3.0,
+                       test-framework-th >= 0.2.0
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+
+test-suite properties
+  type:                 exitcode-stdio-1.0
+  main-is:              properties.hs
+  hs-source-dirs:       test
+  ghc-options:          -W -threaded -rtsopts -with-rtsopts=-N
+  build-depends:        base >=4.6 && <4.7,
+                        bifunctors >= 4.1.1 && <5.0,
+                        hinquire >= 0.1.0,
+                        QuickCheck >= 2.6 && <3.0,
+                        test-framework >=0.8.0,
+                        test-framework-quickcheck2 >=0.3.0,
+                        test-framework-th >= 0.2.0
+  default-language:     Haskell2010
diff --git a/src/Network/Hinquire.hs b/src/Network/Hinquire.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Hinquire.hs
@@ -0,0 +1,178 @@
+module Network.Hinquire where
+
+import Prelude hiding (foldr)
+
+import Control.Applicative (Alternative (..), Applicative, pure, (<*>), (<$>))
+import Control.Monad
+import Data.Biapplicative
+import Data.Bifoldable
+import Data.Bifunctor
+import Data.Bitraversable
+import Data.Char
+import Data.Foldable
+import Data.Monoid
+import Data.Traversable
+
+-- | The relation between a key and value "time=now" or "cat!=dog"
+data Relation = Equal
+              | NEqual
+              | GThan
+              | GThanE
+              | LThan
+              | LThanE
+    deriving Eq
+
+-- | The boolean operation between a group of Inquires
+data GBool = And
+           | Or
+    deriving Eq
+
+-- | This is an optional negation wrapping an Inquire.
+data WBool = NoBool
+           | Not
+    deriving Eq
+
+-- | The meat of our package. This encapsulates our query logic.
+data Inquire k v = Atom
+                 | Predicate k Relation v
+                 | Group (Inquire k v) GBool (Inquire k v)
+                 | Wrap WBool (Inquire k v)
+    deriving Eq
+
+-- Algebra stuff
+
+instance Monoid (Inquire k v) where
+    mempty = Atom
+    mappend = (<&&&>)
+
+instance Functor (Inquire k) where
+    fmap _ Atom = Atom
+    fmap f (Predicate k r v) = Predicate k r (f v)
+    fmap f (Group i1 b i2) = Group (fmap f i1) b (fmap f i2)
+    fmap f (Wrap b i) = Wrap b (fmap f i)
+
+instance Monoid k => Applicative (Inquire k) where
+    pure = Predicate mempty Equal
+
+    Atom <*> _ = Atom
+    _ <*> Atom = Atom
+    (Predicate _ _ f) <*> (Predicate k r v) = Predicate k r (f v)
+    p@Predicate {} <*> (Group i1 b i2) = Group (p <*> i1) b (p <*> i2)
+    p@Predicate {} <*> (Wrap b i) = Wrap b (p <*> i)
+    (Group i1 b i2) <*> i3 = Group (i1 <*> i3) b (i2 <*> i3)
+    (Wrap b i1) <*> i2 = Wrap b (i1 <*> i2)
+
+instance Monoid k => Alternative (Inquire k) where
+    empty = Atom
+
+    Atom <|> i = i
+    i    <|> _ = i
+
+instance Foldable (Inquire k) where
+    foldr _ z Atom = z
+    foldr f z (Predicate _ _ v) = f v z
+    foldr f z (Group i1 _ i2) = foldr f (foldr f z i2) i1
+    foldr f z (Wrap _ i) = foldr f z i
+
+instance Traversable (Inquire k) where
+    traverse _ Atom = pure Atom
+    traverse f (Predicate k r v) = Predicate <$> pure k <*> pure r <*> f v
+    traverse f (Group i1 b i2) =
+        Group <$> traverse f i1 <*> pure b <*> traverse f i1
+    traverse f (Wrap b i) = Wrap <$> pure b <*> traverse f i
+
+instance Monoid k => Monad (Inquire k) where
+    return = Predicate mempty Equal
+
+    Atom >>= _ = Atom
+    -- This seems wrong,
+    -- we've forgotten everything about our Predicate except the value
+    (Predicate _ _ v) >>= f = f v
+    (Group i1 b i2) >>= f = Group (i1 >>= f) b (i2 >>= f)
+    (Wrap b i) >>= f = Wrap b (i >>= f)
+
+instance Bifunctor Inquire where
+    bimap _ _ Atom = Atom
+    bimap f g (Predicate k r v) = Predicate (f k) r (g v)
+    bimap f g (Group i1 b i2) = Group (bimap f g i1) b (bimap f g i2)
+    bimap f g (Wrap b i) = Wrap b (bimap f g i)
+
+instance Bifoldable Inquire where
+    bifoldr _ _ z Atom = z
+    bifoldr f g z (Predicate k _ v) = f k $ g v z
+    bifoldr f g z (Group i1 _ i2) = bifoldr f g (bifoldr f g z i2) i1
+    bifoldr f g z (Wrap _ i) = bifoldr f g z i
+
+instance Biapplicative Inquire where
+    bipure k = Predicate k Equal
+
+    Atom <<*>> _ = Atom
+    _ <<*>> Atom = Atom
+    (Predicate f _ g) <<*>> (Predicate k2 r v2) = Predicate (f k2) r (g v2)
+    p@Predicate {} <<*>> (Group i1 b i2) = Group (p <<*>> i1) b (p <<*>> i2)
+    p@Predicate {} <<*>> (Wrap b i) = Wrap b (p <<*>> i)
+    (Group i1 b i2) <<*>> i3 = Group (i1 <<*>> i3) b (i1 <<*>> i3)
+    (Wrap b i1) <<*>> i2 = Wrap b (i1 <<*>> i2)
+
+instance Bitraversable Inquire where
+    bitraverse _ _ Atom = pure Atom
+    bitraverse f g (Predicate k r v) = Predicate <$> f k <*> pure r <*> g v
+    bitraverse f g (Group i1 b i2) =
+        Group <$> bitraverse f g i1 <*> pure b <*> bitraverse f g i2
+    bitraverse f g (Wrap b i) = Wrap <$> pure b <*> bitraverse f g i
+
+class Dyad d where
+    bireturn :: a -> b -> d a b
+    (>>==) :: d a b -> (a -> b -> d e f) -> d e f
+
+instance Dyad Inquire where
+    bireturn k = Predicate k Equal
+
+    Atom >>== _ = Atom
+    (Predicate k _ v) >>== f = f k v
+    (Group i1 b i2) >>== f = Group (i1 >>== f) b (i2 >>== f)
+    (Wrap b i) >>== f = Wrap b (i >>== f)
+
+-- Show stuff.
+
+instance Show Relation where
+    show Equal  = "="
+    show NEqual = "!="
+    show GThan  = ">"
+    show GThanE = ">="
+    show LThan  = "<"
+    show LThanE = "<="
+
+instance Show GBool where
+    show And = "&"
+    show Or  = ";"
+
+instance Show WBool where
+    show NoBool = ""
+    show Not    = "!"
+
+-- This is really ugly to me, perhaps there's a better way.
+
+instance (Show k, Show v) => Show (Inquire k v) where
+    show Atom = ""
+    show (Predicate k r v) = show k ++ show r ++ show v
+    show (Group Atom _ Atom) = ""
+    show (Group Atom _ r) = show r
+    show (Group l    _ Atom) = show l
+    show (Group l@Predicate {} b r@Predicate {}) = show l ++ show b ++ show r
+    show (Group l@Predicate {} b r) = show l ++ show b ++ "(" ++ show r ++ ")"
+    show (Group l b r@Predicate {}) = "(" ++ show l ++ ")" ++ show b ++ show r
+    show (Group l b r) = "(" ++ show l ++ ")" ++ show b ++ "(" ++ show r ++ ")"
+    show (Wrap n i) = show n ++ "(" ++ show i ++ ")"
+
+-- | Conjoin two Inquires.
+(<&&&>) :: Inquire k v -> Inquire k v -> Inquire k v
+i1 <&&&> i2 = Group i1 And i2
+
+-- | Disjoin two Inquires.
+(<|||>) :: Inquire k v -> Inquire k v -> Inquire k v
+i1 <|||> i2 = Group i1 Or i2
+
+-- | Slap a question mark in front of our inquire.
+generate :: (Show v, Show k) => Inquire k v -> String
+generate = ('?':) . show
diff --git a/test/properties.hs b/test/properties.hs
new file mode 100644
--- /dev/null
+++ b/test/properties.hs
@@ -0,0 +1,185 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+module Main where
+
+import Control.Applicative
+import Control.Monad
+import Data.Biapplicative
+import Data.Bifunctor
+import Data.Bitraversable
+import Network.Hinquire
+import Test.QuickCheck
+import Test.QuickCheck.All
+import Test.QuickCheck.Function
+import Test.Framework.TH
+import Test.Framework.Providers.QuickCheck2
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Fix
+import Data.Foldable (Foldable(foldMap))
+import Data.Traversable (Traversable(traverse))
+
+newtype Identity a = Identity { runIdentity :: a } deriving Eq
+
+instance Functor Identity where
+    fmap f m = Identity (f (runIdentity m))
+
+instance Foldable Identity where
+    foldMap f (Identity x) = f x
+
+instance Traversable Identity where
+    traverse f (Identity x) = Identity <$> f x
+
+instance Applicative Identity where
+    pure a = Identity a
+    Identity f <*> Identity x = Identity (f x)
+
+instance Monad Identity where
+    return a = Identity a
+    m >>= k  = k (runIdentity m)
+
+instance MonadFix Identity where
+    mfix f = Identity (fix (runIdentity . f))
+
+newtype Compose f g a = Compose { getCompose :: f (g a) } deriving Eq
+
+instance (Functor f, Functor g) => Functor (Compose f g) where
+    fmap f (Compose x) = Compose (fmap (fmap f) x)
+
+instance (Foldable f, Foldable g) => Foldable (Compose f g) where
+    foldMap f (Compose t) = foldMap (foldMap f) t
+
+instance (Traversable f, Traversable g) => Traversable (Compose f g) where
+    traverse f (Compose t) = Compose <$> traverse (traverse f) t
+
+instance (Applicative f, Applicative g) => Applicative (Compose f g) where
+    pure x = Compose (pure (pure x))
+    Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
+
+instance (Alternative f, Applicative g) => Alternative (Compose f g) where
+    empty = Compose Control.Applicative.empty
+    Compose x <|> Compose y = Compose (x <|> y)
+
+prop_functor_id :: Inquire String String -> Bool
+prop_functor_id i = fmap id i == i
+
+prop_functor_comp :: Inquire String String
+                  -> Fun String String
+                  -> Fun String String
+                  -> Bool
+prop_functor_comp i (Fun _ f) (Fun _ g) =
+    fmap (f . g) i == fmap f (fmap g i)
+
+prop_bifunctor_id :: Inquire String String -> Bool
+prop_bifunctor_id i = bimap id id i == i
+
+prop_bifunctor_comp :: Inquire String String
+                    -> Fun String String
+                    -> Fun String String
+                    -> Fun String String
+                    -> Fun String String
+                    -> Bool
+prop_bifunctor_comp i (Fun _ f1) (Fun _ g1) (Fun _ f2) (Fun _ g2) =
+    bimap (f1 . g1) (f2 . g2) i == bimap f1 f2 (bimap g1 g2 i)
+
+prop_applicative_id :: Inquire String String -> Bool
+prop_applicative_id i = (pure id <*> i) == i
+
+prop_applicative_composition :: Inquire String String
+                             -> Fun String String
+                             -> Fun String String
+                             -> Bool
+prop_applicative_composition w (Fun _ u1) (Fun _ v1) =
+    (pure (.) <*> u <*> v <*> w) == (u <*> (v <*> w))
+    where u = pure u1
+          v = pure v1
+
+prop_applicative_homomorphism :: Fun String String
+                              -> String
+                              -> Bool
+prop_applicative_homomorphism (Fun _ f) v =
+    (pure f <*> pure v :: Inquire String String) == pure (f v)
+
+prop_applicative_interchange :: Fun String String
+                             -> String
+                             -> Bool
+prop_applicative_interchange (Fun _ f) v =
+    (u <*> pure v :: Inquire String String) == (pure ($ v) <*> u)
+    where u = pure f
+
+prop_biapplicative_id :: Inquire String String -> Bool
+prop_biapplicative_id i = (bipure id id <<*>> i) == i
+
+prop_biapplicative_composition :: Inquire String String
+                               -> Fun String String
+                               -> Fun String String
+                               -> Fun String String
+                               -> Fun String String
+                               -> Bool
+prop_biapplicative_composition w (Fun _ u1) (Fun _ u2) (Fun _ v1) (Fun _ v2) =
+    (bipure (.) (.) <<*>> u <<*>> v <<*>> w) == (u <<*>> (v <<*>> w))
+    where u = bipure u1 u2
+          v = bipure v1 v2
+
+prop_biapplicative_homomorphism :: Fun String String
+                                -> Fun String String
+                                -> String
+                                -> String
+                                -> Bool
+prop_biapplicative_homomorphism (Fun _ f) (Fun _ g) k v =
+    (bipure f g <<*>> bipure k v :: Inquire String String) == bipure (f k) (g v)
+
+prop_biapplicative_interchange :: Fun String String
+                               -> Fun String String
+                               -> String
+                               -> String
+                               -> Bool
+prop_biapplicative_interchange (Fun _ f) (Fun _ g) k v =
+    (u <<*>> bipure k v :: Inquire String String) == (bipure ($ k) ($ v) <<*>> u)
+    where u = bipure f g
+
+prop_bitraversable_id :: Inquire String String -> Bool
+prop_bitraversable_id i =
+    bitraverse Identity Identity i == Identity i
+
+--prop_bitraversable_comp :: Inquire String String
+--                        -> Fun String [String]
+--                        -> Fun String [String]
+--                        -> Fun String [String]
+--                        -> Fun String [String]
+--                        -> Bool
+--prop_bitraversable_comp i (Fun _ f1) (Fun _ f2) (Fun _ g1) (Fun _ g2) =
+--    bitraverse (Compose . fmap g1 . f1) (Compose . fmap g2 . f2) i ==
+--        (Compose . fmap (bitraverse g1 g2) . (bitraverse f1 f2)) i
+
+instance (Arbitrary k, Arbitrary v) => Arbitrary (Inquire k v) where
+    arbitrary = sized inquire
+        where
+            inquire 0 = return Atom
+            inquire 1 = liftM3 Predicate arbitrary rel arbitrary
+            inquire n = oneof [ return Atom
+                              , liftM3 Predicate arbitrary rel arbitrary
+                              , liftM3 Group inquire' gBool inquire'
+                              , liftM2 Wrap wBool inquire'
+                              ]
+                where
+                    inquire' = inquire (n `div` 2)
+            rel = elements [Equal, NEqual, GThan, GThanE, LThan, LThanE]
+            gBool = elements [And, Or]
+            wBool = elements [NoBool, Not]
+
+    shrink Atom              = []
+    shrink (Predicate k r v) = do
+        k' <- shrink k
+        v' <- shrink v
+        return $ Predicate k' r v'
+    shrink (Group i1 b i2)   = do
+        i1' <- shrink i1
+        i2' <- shrink i2
+        return $ Group i1' b i2'
+    shrink (Wrap b i)        = do
+        i' <- shrink i
+        return $ Wrap b i'
+
+main = $defaultMainGenerator
