diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright José Lorenzo Rodríguez (c) 2016
+
+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 Author name 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,41 @@
+mysql-haskell-nem
+=================
+
+Provides a simpler interface for retrieving results when using the [mysql-haskell](http://hackage.haskell.org/package/mysql-haskell) package.
+
+Guide
+-----
+
+The `Database.MySQL.Base` and `Database.MySQL.Nem` modules provides everything you need to start making queries:
+
+```haskell
+{-# LANGUAGE OverloadedStrings #-}
+
+module Main where
+
+import Database.MySQL.Base
+import Database.MySQL.Base.Nem
+import Data.Text (unpack)
+import qualified System.IO.Streams as Streams
+
+main :: IO () 
+main = do
+    conn <- connect
+        defaultConnectInfo {ciUser = "username", ciPassword = "password", ciDatabase = "dbname"}
+
+	results <- queryResults conn "SELECT email, name FROM users" >>=
+	_ <-
+		Streams.mapM_
+			(\(email, name) -> print $ (Text.unpack email) ++ ":" ++ (name :: String) ) results >>=
+		Streams.toList
+```
+
+It's recommended to use prepared statement to improve query speed:
+
+```haskell
+    ...
+    s <- prepareStmt conn "SELECT * FROM some_table where person_age > ?"
+    ...
+    results <- queryStmtResutls s [MySQLInt32U 18]
+    ...
+```
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/mysql-haskell-nem.cabal b/mysql-haskell-nem.cabal
new file mode 100644
--- /dev/null
+++ b/mysql-haskell-nem.cabal
@@ -0,0 +1,34 @@
+name:                mysql-haskell-nem
+version:             0.1.0.0
+synopsis:            Adds a interface like mysql-simple to mysql-haskell.
+description:         Please see README.md
+homepage:            https://github.com/lorenzo/mysql-haskell-nem#readme
+license:             BSD3
+license-file:        LICENSE
+author:              José Lorenzo Rodríguez
+                   , Bryan O'Sullivan
+                   , Paul Rouse
+maintainer:          jose.zap@gmail.com
+copyright:           2016 José Lorenzo Rodríguez
+category:            Database
+build-type:          Simple
+extra-source-files:  Readme.md
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Database.MySQL.Nem
+                     , Database.MySQL.Nem.QueryResults
+                     , Database.MySQL.Nem.Result
+  build-depends:       base >= 4.7 && < 5
+                     , mysql-haskell
+                     , bytestring
+                     , text
+                     , time
+                     , scientific
+                     , io-streams
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/lorenzo/mysql-haskell-nem
diff --git a/src/Database/MySQL/Nem.hs b/src/Database/MySQL/Nem.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/MySQL/Nem.hs
@@ -0,0 +1,74 @@
+module Database.MySQL.Nem
+  ( module Database.MySQL.Nem.QueryResults
+  , module Database.MySQL.Nem.Result
+   -- * Extracting results
+   -- $result
+  , queryResults
+  , queryStmtResults
+  ) where
+
+import Database.MySQL.Base
+import Database.MySQL.Nem.QueryResults
+import Database.MySQL.Nem.Result
+import qualified System.IO.Streams as Streams
+
+-- | Execute a MySQL query which return a result-set converted to the specified
+-- haskell type
+--
+-- Note that you must fully consumed the result-set before start a new query on
+-- the same 'MySQLConn', or an 'UnconsumedResultSet' will be thrown.
+-- if you want to skip the result-set, use 'Stream.skipToEof'.
+--
+queryResults
+  :: (QueryResults r)
+  => MySQLConn -> Query -> IO (Streams.InputStream r)
+queryResults conn qry = do
+  (defs, results) <- query_ conn qry
+  Streams.map (convertResults defs) results
+
+-- | Execute prepared query statement with parameters, expecting resultset.
+--
+--
+-- Note that you must fully consumed the result-set before start a new query on
+-- the same 'MySQLConn', or an 'UnconsumedResultSet' will be thrown.
+-- if you want to skip the result-set, use 'Stream.skipToEof'.
+--
+queryStmtResults
+  :: (QueryResults r)
+  => MySQLConn -> StmtID -> [MySQLValue] -> IO (Streams.InputStream r)
+queryStmtResults conn qry params = do
+  (defs, results) <- queryStmt conn qry params
+  Streams.map (convertResults defs) results
+--
+-- $result
+--
+-- The 'queryResults' and 'queryStmtResults' functions return a list of values in the
+-- 'QueryResults' typeclass. This class performs automatic extraction
+-- and type conversion of rows from a query result.
+--
+-- Here is a simple example of how to extract results:
+--
+-- > import qualified Data.Text as Text
+-- > import Database.MySQL.Nem
+-- > import qualified System.IO.Streams as Streams
+-- >
+-- > xs <- queryResults conn "select name,age from users"
+-- > Streams.mapM_
+-- >    \(name,age) ->
+-- >       putStrLn $ Text.unpack name ++ " is " ++ show (age :: Int)
+-- >    xs
+--
+-- Notice two important details about this code:
+--
+-- * The number of columns we ask for in the query template must
+--   exactly match the number of elements we specify in a row of the
+--   result tuple.  If they do not match, a 'ResultError' exception
+--   will be thrown.
+--
+-- * Sometimes, the compiler needs our help in specifying types. It
+--   can infer that @name@ must be a 'Text', due to our use of the
+--   @unpack@ function. However, we have to tell it the type of @age@,
+--   as it has no other information to determine the exact type.
+--
+--   For converting to your custom data types. Check the documentation for
+--   the QueryResults package.
diff --git a/src/Database/MySQL/Nem/QueryResults.hs b/src/Database/MySQL/Nem/QueryResults.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/MySQL/Nem/QueryResults.hs
@@ -0,0 +1,711 @@
+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
+
+-- |
+-- Module:      Database.MySQL.Simpe.QueryResults
+-- Copyright:   (c) 2011 MailRank, Inc.
+-- License:     BSD3
+-- Maintainer:  José Lorenzo Rodríguez
+-- Stability:   experimental
+-- Portability: portable
+--
+-- The 'QueryResults' typeclass, for converting a row of results
+-- returned by a SQL query into a more useful Haskell representation.
+--
+-- Predefined instances are provided for tuples containing up to 24
+-- elements.
+module Database.MySQL.Nem.QueryResults
+  ( QueryResults(..)
+  , convertError
+  ) where
+
+import Control.Exception (throw)
+import Database.MySQL.Base (ColumnDef(..), MySQLValue)
+import Database.MySQL.Nem.Result (ResultError(..), Result(..))
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as B8
+
+-- | A collection type that can be converted from a MySQL row result.
+--
+-- Instances should use the 'convert' method of the 'Result' class
+-- to perform conversion of each element of the collection.
+--
+-- This example instance demonstrates how to convert a two-column row
+-- into a Haskell pair. Each field in the metadata is paired up with
+-- each value from the row, and the two are passed to 'convert'.
+--
+-- @
+-- instance ('Result' a, 'Result' b) => 'QueryResults' (a,b) where
+--     'convertResults' [fa,fb] [va,vb] = (a,b)
+--         where !a = 'convert' fa va
+--               !b = 'convert' fb vb
+--     'convertResults' fs vs  = 'convertError' fs vs 2
+-- @
+--
+-- Notice that this instance evaluates each element to WHNF before
+-- constructing the pair. By doing this, we guarantee two important
+-- properties:
+--
+-- * Keep resource usage under control by preventing the construction
+--   of potentially long-lived thunks.
+--
+-- * Ensure that any 'ResultError' that might arise is thrown
+--   immediately, rather than some place later in application code
+--   that cannot handle it.
+--
+-- You can also declare Haskell types of your own to be instances of
+-- 'QueryResults'.
+--
+-- @
+--data User = User { firstName :: String, lastName :: String }
+--
+--instance 'QueryResults' User where
+--    'convertResults' [fa,fb] [va,vb] = User <$> a <*> b
+--        where !a = 'convert' fa va
+--              !b = 'convert' fb vb
+--    'convertResults' fs vs  = 'convertError' fs vs 2
+-- @
+class QueryResults a
+      -- Convert values from a row into a Haskell collection.
+      --
+      -- This function will throw a 'ResultError' if conversion of the
+      -- collection fails.
+        where
+  convertResults :: [ColumnDef] -> [MySQLValue] -> a
+
+instance (Result a, Result b) =>
+         QueryResults (a, b) where
+  convertResults [fa, fb] [va, vb] = (a, b)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+  convertResults fs vs = convertError fs vs 2
+
+instance (Result a, Result b, Result c) =>
+         QueryResults (a, b, c) where
+  convertResults [fa, fb, fc] [va, vb, vc] = (a, b, c)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+  convertResults fs vs = convertError fs vs 3
+
+instance (Result a, Result b, Result c, Result d) =>
+         QueryResults (a, b, c, d) where
+  convertResults [fa, fb, fc, fd] [va, vb, vc, vd] = (a, b, c, d)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+  convertResults fs vs = convertError fs vs 4
+
+instance (Result a, Result b, Result c, Result d, Result e) =>
+         QueryResults (a, b, c, d, e) where
+  convertResults [fa, fb, fc, fd, fe] [va, vb, vc, vd, ve] = (a, b, c, d, e)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+  convertResults fs vs = convertError fs vs 5
+
+instance (Result a, Result b, Result c, Result d, Result e, Result f) =>
+         QueryResults (a, b, c, d, e, f) where
+  convertResults [fa, fb, fc, fd, fe, ff] [va, vb, vc, vd, ve, vf] =
+    (a, b, c, d, e, f)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+  convertResults fs vs = convertError fs vs 6
+
+instance (Result a, Result b, Result c, Result d, Result e, Result f, Result g) =>
+         QueryResults (a, b, c, d, e, f, g) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg] [va, vb, vc, vd, ve, vf, vg] =
+    (a, b, c, d, e, f, g)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+  convertResults fs vs = convertError fs vs 7
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h) =>
+         QueryResults (a, b, c, d, e, f, g, h) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh] [va, vb, vc, vd, ve, vf, vg, vh] =
+    (a, b, c, d, e, f, g, h)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+  convertResults fs vs = convertError fs vs 8
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i) =>
+         QueryResults (a, b, c, d, e, f, g, h, i) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi] [va, vb, vc, vd, ve, vf, vg, vh, vi] =
+    (a, b, c, d, e, f, g, h, i)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+  convertResults fs vs = convertError fs vs 9
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj] =
+    (a, b, c, d, e, f, g, h, i, j)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+  convertResults fs vs = convertError fs vs 10
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk] =
+    (a, b, c, d, e, f, g, h, i, j, k)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+  convertResults fs vs = convertError fs vs 11
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl] =
+    (a, b, c, d, e, f, g, h, i, j, k, l)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+  convertResults fs vs = convertError fs vs 12
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+  convertResults fs vs = convertError fs vs 13
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m
+         ,Result n) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m, n)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+      !n = convert fn vn
+  convertResults fs vs = convertError fs vs 14
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m
+         ,Result n
+         ,Result o) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, fo] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+      !n = convert fn vn
+      !o = convert fo vo
+  convertResults fs vs = convertError fs vs 15
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m
+         ,Result n
+         ,Result o
+         ,Result p) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, fo, fp] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+      !n = convert fn vn
+      !o = convert fo vo
+      !p = convert fp vp
+  convertResults fs vs = convertError fs vs 16
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m
+         ,Result n
+         ,Result o
+         ,Result p
+         ,Result q) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, fo, fp, fq] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+      !n = convert fn vn
+      !o = convert fo vo
+      !p = convert fp vp
+      !q = convert fq vq
+  convertResults fs vs = convertError fs vs 17
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m
+         ,Result n
+         ,Result o
+         ,Result p
+         ,Result q
+         ,Result r) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, fo, fp, fq, fr] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq, vr] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+      !n = convert fn vn
+      !o = convert fo vo
+      !p = convert fp vp
+      !q = convert fq vq
+      !r = convert fr vr
+  convertResults fs vs = convertError fs vs 18
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m
+         ,Result n
+         ,Result o
+         ,Result p
+         ,Result q
+         ,Result r
+         ,Result s) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, fo, fp, fq, fr, fs] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq, vr, vs] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+      !n = convert fn vn
+      !o = convert fo vo
+      !p = convert fp vp
+      !q = convert fq vq
+      !r = convert fr vr
+      !s = convert fs vs
+  convertResults fs_ vs_ = convertError fs_ vs_ 19
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m
+         ,Result n
+         ,Result o
+         ,Result p
+         ,Result q
+         ,Result r
+         ,Result s
+         ,Result t
+         ,Result u
+         ,Result v) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, fo, fp, fq, fr, fs, ft, fu, fv] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq, vr, vs, vt, vu, vv] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+      !n = convert fn vn
+      !o = convert fo vo
+      !p = convert fp vp
+      !q = convert fq vq
+      !r = convert fr vr
+      !s = convert fs vs
+      !t = convert ft vt
+      !u = convert fu vu
+      !v = convert fv vv
+  convertResults fs_ vs_ = convertError fs_ vs_ 22
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m
+         ,Result n
+         ,Result o
+         ,Result p
+         ,Result q
+         ,Result r
+         ,Result s
+         ,Result t
+         ,Result u
+         ,Result v
+         ,Result w) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, fo, fp, fq, fr, fs, ft, fu, fv, fw] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq, vr, vs, vt, vu, vv, vw] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+      !n = convert fn vn
+      !o = convert fo vo
+      !p = convert fp vp
+      !q = convert fq vq
+      !r = convert fr vr
+      !s = convert fs vs
+      !t = convert ft vt
+      !u = convert fu vu
+      !v = convert fv vv
+      !w = convert fw vw
+  convertResults fs_ vs_ = convertError fs_ vs_ 23
+
+instance (Result a
+         ,Result b
+         ,Result c
+         ,Result d
+         ,Result e
+         ,Result f
+         ,Result g
+         ,Result h
+         ,Result i
+         ,Result j
+         ,Result k
+         ,Result l
+         ,Result m
+         ,Result n
+         ,Result o
+         ,Result p
+         ,Result q
+         ,Result r
+         ,Result s
+         ,Result t
+         ,Result u
+         ,Result v
+         ,Result w
+         ,Result x) =>
+         QueryResults (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) where
+  convertResults [fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, fo, fp, fq, fr, fs, ft, fu, fv, fw, fx] [va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq, vr, vs, vt, vu, vv, vw, vx] =
+    (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x)
+    where
+      !a = convert fa va
+      !b = convert fb vb
+      !c = convert fc vc
+      !d = convert fd vd
+      !e = convert fe ve
+      !f = convert ff vf
+      !g = convert fg vg
+      !h = convert fh vh
+      !i = convert fi vi
+      !j = convert fj vj
+      !k = convert fk vk
+      !l = convert fl vl
+      !m = convert fm vm
+      !n = convert fn vn
+      !o = convert fo vo
+      !p = convert fp vp
+      !q = convert fq vq
+      !r = convert fr vr
+      !s = convert fs vs
+      !t = convert ft vt
+      !u = convert fu vu
+      !v = convert fv vv
+      !w = convert fw vw
+      !x = convert fx vx
+  convertResults fs_ vs_ = convertError fs_ vs_ 24
+
+-- | Throw a 'ConversionFailed' exception, indicating a mismatch
+-- between the number of columns in the 'Field' and row, and the
+-- number in the collection to be converted to.
+convertError
+  :: [ColumnDef]
+     -- ^ Descriptors of fields to be converted.
+  -> [MySQLValue]
+     -- ^ Contents of the row to be converted.
+  -> Int
+     -- ^ Number of columns expected for conversion.  For
+     -- instance, if converting to a 3-tuple, the number to
+     -- provide here would be 3.
+  -> a
+convertError fs vs n =
+  throw $
+  ConversionFailed
+    (show (map (B8.unpack . columnName) fs))
+    ("Tried to create a Tuple of " ++ show n ++ " elements")
+    ("Mismatch between number of columns to convert and number in target type. Source: " ++
+     (show . length) vs ++ " columns, Target: " ++ show n ++ " elements")
diff --git a/src/Database/MySQL/Nem/Result.hs b/src/Database/MySQL/Nem/Result.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/MySQL/Nem/Result.hs
@@ -0,0 +1,170 @@
+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances #-}
+
+-- |
+-- Module:      Database.MySQL.Simple.Result
+-- Copyright:   (c) 2011 MailRank, Inc.
+-- License:     BSD3
+-- Maintainer:  José Lorenzo Rodríguez
+-- Stability:   experimental
+-- Portability: portable
+--
+-- The 'Result' typeclass, for converting a single value in a row
+-- returned by a SQL query into a more useful Haskell representation.
+--
+-- A Haskell numeric type is considered to be compatible with all
+-- MySQL numeric types that are less accurate than it. For instance,
+-- the Haskell 'Double' type is compatible with the MySQL 'Long' type
+-- because it can represent a 'Long' exactly. On the other hand, since
+-- a 'Double' might lose precision if representing a 'LongLong', the
+-- two are /not/ considered compatible.
+module Database.MySQL.Nem.Result
+  ( ResultError(..)
+  , Result(..)
+  ) where
+
+import Control.Exception (Exception, throw)
+import Data.Int
+import Data.Scientific (Scientific, fromFloatDigits)
+import Data.Time.Calendar (Day)
+import Data.Time.LocalTime (LocalTime)
+import Data.Typeable (Typeable)
+import Database.MySQL.Base (MySQLValue(..), ColumnDef(..))
+import qualified Data.ByteString as ByteString (ByteString, unpack)
+import qualified Data.Text as Text (Text, unpack)
+
+-- | Exception thrown if conversion from a SQL value to a Haskell
+-- value fails.
+data ResultError
+  = Incompatible { errColumnName :: String
+                 , errHaskellType :: String
+                 , errMessage :: String}
+  | ConversionFailed { errColumnName :: String
+                     , errHaskellType :: String
+                     , errMessage :: String}
+  deriving (Eq, Show, Typeable)
+
+instance Exception ResultError
+
+-- | A type that may be converted from a SQL type.
+class Result a  where
+  convert :: ColumnDef -> MySQLValue -> a -- Convert a MySQLValue to another value
+
+instance (Result a) =>
+         Result (Maybe a) where
+  convert def val =
+    case val of
+      MySQLNull -> Nothing
+      _ -> Just $ convert def val
+
+instance Result Int where
+  convert = intConvert "Int"
+
+instance Result Int8 where
+  convert def val =
+    case val of
+      MySQLInt8U i -> fromIntegral i
+      MySQLInt8 i -> fromIntegral i
+      _ -> throw $ conversionFailed "Int8" val def
+
+instance Result Int16 where
+  convert def val =
+    case val of
+      MySQLInt8U i -> fromIntegral i
+      MySQLInt16U i -> fromIntegral i
+      MySQLInt8 i -> fromIntegral i
+      MySQLInt16 i -> fromIntegral i
+      _ -> throw $ conversionFailed "Int16" val def
+
+instance Result Int32 where
+  convert def val =
+    case val of
+      MySQLInt8U i -> fromIntegral i
+      MySQLInt16U i -> fromIntegral i
+      MySQLInt32U i -> fromIntegral i
+      MySQLInt8 i -> fromIntegral i
+      MySQLInt16 i -> fromIntegral i
+      MySQLInt32 i -> fromIntegral i
+      _ -> throw $ conversionFailed "Int32" val def
+
+instance Result Int64 where
+  convert = intConvert "Int64"
+
+instance Result Float where
+  convert def val =
+    case val of
+      MySQLFloat f -> f
+      _ -> throw $ conversionFailed "Float" val def
+
+instance Result Double where
+  convert def val =
+    case val of
+      MySQLDouble d -> d
+      _ -> throw $ conversionFailed "Double" val def
+
+instance Result Text.Text where
+  convert def val =
+    case val of
+      MySQLText t -> t
+      _ -> throw $ conversionFailed "Text" val def
+
+instance Result String where
+  convert def val =
+    case val of
+      MySQLText t -> Text.unpack t
+      _ -> throw $ conversionFailed "String" val def
+
+instance Result ByteString.ByteString where
+  convert def val =
+    case val of
+      MySQLBytes t -> t
+      _ -> throw $ conversionFailed "ByteString" val def
+
+instance Result Day where
+  convert def val =
+    case val of
+      MySQLDate d -> d
+      _ -> throw $ conversionFailed "Day" val def
+
+instance Result LocalTime where
+  convert def val =
+    case val of
+      MySQLDateTime d -> d
+      MySQLTimeStamp d -> d
+      _ -> throw $ conversionFailed "LocalTime" val def
+
+instance Result Scientific where
+  convert def val =
+    case val of
+      MySQLDecimal d -> d
+      MySQLFloat f -> fromFloatDigits f
+      MySQLDouble f -> fromFloatDigits f
+      MySQLInt8U i -> fromIntegral i
+      MySQLInt16U i -> fromIntegral i
+      MySQLInt32U i -> fromIntegral i
+      MySQLInt64U i -> fromIntegral i
+      MySQLInt8 i -> fromIntegral i
+      MySQLInt16 i -> fromIntegral i
+      MySQLInt32 i -> fromIntegral i
+      MySQLInt64 i -> fromIntegral i
+      _ -> throw $ conversionFailed "Scientific" val def
+
+intConvert
+  :: Num a
+  => String -> ColumnDef -> MySQLValue -> a
+intConvert t def val =
+  case val of
+    MySQLInt8U i -> fromIntegral i
+    MySQLInt16U i -> fromIntegral i
+    MySQLInt32U i -> fromIntegral i
+    MySQLInt64U i -> fromIntegral i
+    MySQLInt8 i -> fromIntegral i
+    MySQLInt16 i -> fromIntegral i
+    MySQLInt32 i -> fromIntegral i
+    MySQLInt64 i -> fromIntegral i
+    _ -> throw $ conversionFailed t val def
+
+conversionFailed t v def =
+  Incompatible
+    (show . ByteString.unpack . columnName $ def)
+    t
+    ("Could not convert: " ++ show v)
