diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.6.7003.0
+
+* Add `tableField` as a future replacement for `tableColumn`
+
+* Export `Opaleye.Field` and `Opaleye.RunSelect` from `Opaleye`
+
+* Use new nomenclature in tutorials
+
 ## 0.6.7002.0
 
 This is a breaking release that doesn't follow the PVP but because
diff --git a/Doc/Tutorial/TutorialBasic.lhs b/Doc/Tutorial/TutorialBasic.lhs
--- a/Doc/Tutorial/TutorialBasic.lhs
+++ b/Doc/Tutorial/TutorialBasic.lhs
@@ -8,12 +8,12 @@
 >
 > import           Prelude hiding (sum)
 >
-> import           Opaleye (Column, Nullable, matchNullable, isNull,
->                          Table, table, tableColumn, queryTable,
->                          Query, QueryArr, restrict, (.==), (.<=), (.&&), (.<),
+> import           Opaleye (Field, FieldNullable, matchNullable, isNull,
+>                          Table, table, tableField, selectTable,
+>                          Select, SelectArr, restrict, (.==), (.<=), (.&&), (.<),
 >                          (.===),
 >                          (.++), ifThenElse, sqlString, aggregate, groupBy,
->                          count, avg, sum, leftJoin, runQuery,
+>                          count, avg, sum, leftJoin, runSelect,
 >                          showSqlForPostgres, Unpackspec,
 >                          SqlInt4, SqlInt8, SqlText, SqlDate, SqlFloat8, SqlBool)
 >
@@ -59,17 +59,17 @@
 `Table` types will have the same type argument repeated twice.  In the
 manipulation tutorial you can see an example of when they might differ.
 
-> personTable :: Table (Column SqlText, Column SqlInt4, Column SqlText)
->                      (Column SqlText, Column SqlInt4, Column SqlText)
-> personTable = table "personTable" (p3 ( tableColumn "name"
->                                       , tableColumn "age"
->                                       , tableColumn "address" ))
+> personTable :: Table (Field SqlText, Field SqlInt4, Field SqlText)
+>                      (Field SqlText, Field SqlInt4, Field SqlText)
+> personTable = table "personTable" (p3 ( tableField "name"
+>                                       , tableField "age"
+>                                       , tableField "address" ))
 
 By default, the table `"personTable"` is looked up in PostgreSQL's
 default `"public"` schema. If we wanted to specify a different schema we
 could have used the `tableWithSchema` function instead of `table`.
 
-To query a table we use `queryTable`.
+To query a table we use `selectTable`.
 
 (Here and in a few other places in Opaleye there is some typeclass
 magic going on behind the scenes to reduce boilerplate.  However, you
@@ -79,13 +79,13 @@
 because they are simpler to read and the typeclass magic is
 essentially invisible.)
 
-> personQuery :: Query (Column SqlText, Column SqlInt4, Column SqlText)
-> personQuery = queryTable personTable
+> personSelect :: Select (Field SqlText, Field SqlInt4, Field SqlText)
+> personSelect = selectTable personTable
 
-A `Query` corresponds to an SQL SELECT that we can run.  Here is the
-SQL generated for `personQuery`.
+A `Select` corresponds to an SQL SELECT that we can run.  Here is the
+SQL generated for `personSelect`.
 
-ghci> printSql personQuery
+ghci> printSql personSelect
 SELECT name0_1 as result1,
        age1_1 as result2,
        address2_1 as result3
@@ -126,7 +126,7 @@
 
 > data Birthday' a b = Birthday { bdName :: a, bdDay :: b }
 > type Birthday = Birthday' String Day
-> type BirthdayColumn = Birthday' (Column SqlText) (Column SqlDate)
+> type BirthdayField = Birthday' (Field SqlText) (Field SqlDate)
 
 To get user defined types to work with the typeclass magic they must
 have instances defined for them.  The instances are derivable with
@@ -141,15 +141,15 @@
 Then we can use 'table' to make a table on our record type in exactly
 the same way as before.
 
-> birthdayTable :: Table BirthdayColumn BirthdayColumn
+> birthdayTable :: Table BirthdayField BirthdayField
 > birthdayTable = table "birthdayTable"
->                        (pBirthday Birthday { bdName = tableColumn "name"
->                                            , bdDay  = tableColumn "birthday" })
+>                        (pBirthday Birthday { bdName = tableField "name"
+>                                            , bdDay  = tableField "birthday" })
 >
-> birthdayQuery :: Query BirthdayColumn
-> birthdayQuery = queryTable birthdayTable
+> birthdaySelect :: Select BirthdayField
+> birthdaySelect = selectTable birthdayTable
 
-ghci> printSql birthdayQuery
+ghci> printSql birthdaySelect
 SELECT name0_1 as result1,
        birthday1_1 as result2
 FROM (SELECT *
@@ -169,7 +169,7 @@
 
 "Projection" means discarding some of the columns of our query, for
 example we might want to discard the "address" column of our
-`personQuery`.
+`personSelect`.
 
 Projection gives us our first example of using "arrow notation" to
 write Opaleye queries.  Arrow notation is essentially a restricted
@@ -177,13 +177,13 @@
 computations, and do notation allows you to write monadic
 computations.
 
-Here we run the `personQuery` passing in () to signify "zero
+Here we run the `personSelect` passing in () to signify "zero
 arguments".  We pattern match on the results and return only the
 columns we are interested in.
 
-> nameAge :: Query (Column SqlText, Column SqlInt4)
+> nameAge :: Select (Field SqlText, Field SqlInt4)
 > nameAge = proc () -> do
->   (name, age, _) <- personQuery -< ()
+>   (name, age, _) <- personSelect -< ()
 >   returnA -< (name, age)
 
 ghci> printSql nameAge
@@ -205,14 +205,14 @@
 =======
 
 "Product" means taking the Cartesian product of two queries.  This is
-simple in arrow notation.  Here we take the product of `personQuery`
-and `birthdayQuery`.
+simple in arrow notation.  Here we take the product of `personSelect`
+and `birthdaySelect`.
 
 > personBirthdayProduct ::
->   Query ((Column SqlText, Column SqlInt4, Column SqlText), BirthdayColumn)
+>   Select ((Field SqlText, Field SqlInt4, Field SqlText), BirthdayField)
 > personBirthdayProduct = proc () -> do
->   personRow   <- personQuery -< ()
->   birthdayRow <- birthdayQuery -< ()
+>   personRow   <- personSelect -< ()
+>   birthdayRow <- birthdaySelect -< ()
 >
 >   returnA -< (personRow, birthdayRow)
 
@@ -253,12 +253,12 @@
 "Restriction" means restricting the rows of the result of a query to
 only those where some condition holds.
 
-We can restrict `personQuery` to the rows where the person is up to 18
+We can restrict `personSelect` to the rows where the person is up to 18
 years old.
 
-> youngPeople :: Query (Column SqlText, Column SqlInt4, Column SqlText)
+> youngPeople :: Select (Field SqlText, Field SqlInt4, Field SqlText)
 > youngPeople = proc () -> do
->   row@(_, age, _) <- personQuery -< ()
+>   row@(_, age, _) <- personSelect -< ()
 >   restrict -< age .<= 18
 >
 >   returnA -< row
@@ -286,9 +286,9 @@
 We can use a variety of operators to form more complex restriction
 conditions.
 
-> twentiesAtAddress :: Query (Column SqlText, Column SqlInt4, Column SqlText)
+> twentiesAtAddress :: Select (Field SqlText, Field SqlInt4, Field SqlText)
 > twentiesAtAddress = proc () -> do
->   row@(_, age, address) <- personQuery -< ()
+>   row@(_, age, address) <- personSelect -< ()
 >
 >   restrict -< (20 .<= age) .&& (age .< 30)
 >   restrict -< address .== sqlString "1 My Street, My Town"
@@ -327,10 +327,10 @@
 such.
 
 > personAndBirthday ::
->   Query (Column SqlText, Column SqlInt4, Column SqlText, Column SqlDate)
+>   Select (Field SqlText, Field SqlInt4, Field SqlText, Field SqlDate)
 > personAndBirthday = proc () -> do
->   (name, age, address) <- personQuery -< ()
->   birthday             <- birthdayQuery -< ()
+>   (name, age, address) <- personSelect -< ()
+>   birthday             <- birthdaySelect -< ()
 >
 >   restrict -< name .== bdName birthday
 >
@@ -380,17 +380,17 @@
 of each employee and the name of their boss.  If their boss is
 recorded as NULL then that means they have no boss!
 
-> employeeTable :: Table (Column SqlText, Column (Nullable SqlText))
->                        (Column SqlText, Column (Nullable SqlText))
-> employeeTable = table "employeeTable" (p2 ( tableColumn "name"
->                                           , tableColumn "boss" ))
+> employeeTable :: Table (Field SqlText, FieldNullable SqlText)
+>                        (Field SqlText, FieldNullable SqlText)
+> employeeTable = table "employeeTable" (p2 ( tableField "name"
+>                                           , tableField "boss" ))
 
 We can write a query that returns as string indicating for each
 employee whether they have a boss.
 
-> hasBoss :: Query (Column SqlText)
+> hasBoss :: Select (Field SqlText)
 > hasBoss = proc () -> do
->   (name, nullableBoss) <- queryTable employeeTable -< ()
+>   (name, nullableBoss) <- selectTable employeeTable -< ()
 >
 >   let aOrNo = ifThenElse (isNull nullableBoss) (sqlString "no") (sqlString "a")
 >
@@ -419,8 +419,8 @@
 returns its first argument.  If not it passes the non-NULL value to
 the function that is the second argument.
 
-> bossQuery :: QueryArr (Column SqlText, Column (Nullable SqlText)) (Column SqlText)
-> bossQuery = proc (name, nullableBoss) -> do
+> bossSelect :: SelectArr (Field SqlText, FieldNullable SqlText) (Field SqlText)
+> bossSelect = proc (name, nullableBoss) -> do
 >   returnA -< matchNullable (name .++ sqlString " has no boss")
 >                            (\boss -> sqlString "The boss of " .++ name
 >                                      .++ sqlString " is " .++ boss)
@@ -440,7 +440,7 @@
 
 Then we get the following SQL.
 
-ghci> printSql (bossQuery <<< queryTable employeeTable)
+ghci> printSql (bossSelect <<< selectTable employeeTable)
 
 SELECT CASE WHEN boss1_1 IS NULL THEN (name0_1) || ' has no boss'
      ELSE (('The boss of ' || (name0_1)) || ' is ') || (boss1_1) END as result1
@@ -469,28 +469,28 @@
 twenties" and the restriction to the one's address being "1 My Street,
 My Town".
 
-The types are of the form `QueryArr a ()`.  This means that they read
-columns of type `a` but do not return any columns.  (Note: `Query` is
-just a synonym for `QueryArr ()` which means that it is a `QueryArr`
+The types are of the form `SelectArr a ()`.  This means that they read
+columns of type `a` but do not return any columns.  (Note: `Select` is
+just a synonym for `SelectArr ()` which means that it is a `SelectArr`
 that does not read any columns.)
 
-> restrictIsTwenties :: QueryArr (Column SqlInt4) ()
+> restrictIsTwenties :: SelectArr (Field SqlInt4) ()
 > restrictIsTwenties = proc age -> do
 >   restrict -< (20 .<= age) .&& (age .< 30)
 >
-> restrictAddressIs1MyStreet :: QueryArr (Column SqlText) ()
+> restrictAddressIs1MyStreet :: SelectArr (Field SqlText) ()
 > restrictAddressIs1MyStreet = proc address -> do
 >   restrict -< address .== sqlString "1 My Street, My Town"
 
 We can't generate "the SQL of" these combinators.  They are not
-`Query`s so they don't have any SQL!  (This corresponds to the
+`Select`s so they don't have any SQL!  (This corresponds to the
 observation that in Haskell typically values can be "shown", but
 functions cannot be "shown".) Instead we use them to reimplement
 `twentiesAtAddress` in a more neatly-factored way.
 
-> twentiesAtAddress' :: Query (Column SqlText, Column SqlInt4, Column SqlText)
+> twentiesAtAddress' :: Select (Field SqlText, Field SqlInt4, Field SqlText)
 > twentiesAtAddress' = proc () -> do
->   row@(_, age, address) <- personQuery -< ()
+>   row@(_, age, address) <- personSelect -< ()
 >
 >   restrictIsTwenties -< age
 >   restrictAddressIs1MyStreet -< address
@@ -516,12 +516,12 @@
 ----------------------
 
 We can perform a similar transformation for `personAndBirthday` by
-pulling out a `QueryArr` which perform the mapping of a person's name
-to their date of birth by looking up in `birthdayQuery`.
+pulling out a `SelectArr` which perform the mapping of a person's name
+to their date of birth by looking up in `birthdaySelect`.
 
-> birthdayOfPerson :: QueryArr (Column SqlText) (Column SqlDate)
+> birthdayOfPerson :: SelectArr (Field SqlText) (Field SqlDate)
 > birthdayOfPerson = proc name -> do
->   birthday <- birthdayQuery -< ()
+>   birthday <- birthdaySelect -< ()
 >
 >   restrict -< name .== bdName birthday
 >
@@ -530,9 +530,9 @@
 We can then reimplement `personAndBirthday` as follows
 
 > personAndBirthday' ::
->   Query (Column SqlText, Column SqlInt4, Column SqlText, Column SqlDate)
+>   Select (Field SqlText, Field SqlInt4, Field SqlText, Field SqlDate)
 > personAndBirthday' = proc () -> do
->   (name, age, address) <- personQuery -< ()
+>   (name, age, address) <- personSelect -< ()
 >   birthday <- birthdayOfPerson -< name
 >
 >   returnA -< (name, age, address, birthday)
@@ -580,16 +580,16 @@
 For the purposes of this example the style, color and location will be
 strings, but in practice they might have been a different data type.
 
-> widgetTable :: Table (Widget (Column SqlText) (Column SqlText) (Column SqlText)
->                              (Column SqlInt4) (Column SqlFloat8))
->                      (Widget (Column SqlText) (Column SqlText) (Column SqlText)
->                              (Column SqlInt4) (Column SqlFloat8))
+> widgetTable :: Table (Widget (Field SqlText) (Field SqlText) (Field SqlText)
+>                              (Field SqlInt4) (Field SqlFloat8))
+>                      (Widget (Field SqlText) (Field SqlText) (Field SqlText)
+>                              (Field SqlInt4) (Field SqlFloat8))
 > widgetTable = table "widgetTable"
->                      (pWidget Widget { style    = tableColumn "style"
->                                      , color    = tableColumn "color"
->                                      , location = tableColumn "location"
->                                      , quantity = tableColumn "quantity"
->                                      , radius   = tableColumn "radius" })
+>                      (pWidget Widget { style    = tableField "style"
+>                                      , color    = tableField "color"
+>                                      , location = tableField "location"
+>                                      , quantity = tableField "quantity"
+>                                      , radius   = tableField "radius" })
 
 
 Say we want to group by the style and color of widgets, calculating
@@ -597,14 +597,14 @@
 of such widgets and their average radius.  `aggregateWidgets` shows us
 how to do this.
 
-> aggregateWidgets :: Query (Widget (Column SqlText) (Column SqlText) (Column SqlInt8)
->                                   (Column SqlInt4) (Column SqlFloat8))
+> aggregateWidgets :: Select (Widget (Field SqlText) (Field SqlText) (Field SqlInt8)
+>                                   (Field SqlInt4) (Field SqlFloat8))
 > aggregateWidgets = aggregate (pWidget Widget { style    = groupBy
 >                                              , color    = groupBy
 >                                              , location = count
 >                                              , quantity = sum
 >                                              , radius   = avg })
->                              (queryTable widgetTable)
+>                              (selectTable widgetTable)
 
 The generated SQL is
 
@@ -644,8 +644,8 @@
 uses of our Template Haskell derived code.  We use the 'pWidget'
 "adaptor" to specify how columns are aggregated.  Note that this is
 yet another example of avoiding a headache by keeping your datatype
-fully polymorphic, because the 'count' aggregator changes a 'Column
-String' into a 'Column Int64'.
+fully polymorphic, because the 'count' aggregator changes a 'Field
+String' into a 'Field Int64'.
 
 Outer join
 ==========
@@ -659,15 +659,15 @@
 nullability.  We introduce the following type synonym for this
 purpose, which is just a notational convenience.
 
-> type ColumnNullableBirthday = Birthday' (Column (Nullable SqlText))
->                                         (Column (Nullable SqlDate))
+> type FieldNullableBirthday = Birthday' (FieldNullable SqlText)
+>                                         (FieldNullable SqlDate)
 
 A left join is expressed by specifying the two tables to join and the
 join condition.
 
-> personBirthdayLeftJoin :: Query ((Column SqlText, Column SqlInt4, Column SqlText),
->                                  ColumnNullableBirthday)
-> personBirthdayLeftJoin = leftJoin personQuery birthdayQuery eqName
+> personBirthdayLeftJoin :: Select ((Field SqlText, Field SqlInt4, Field SqlText),
+>                                  FieldNullableBirthday)
+> personBirthdayLeftJoin = leftJoin personSelect birthdaySelect eqName
 >     where eqName ((name, _, _), birthdayRow) = name .== bdName birthdayRow
 
 The generated SQL is
@@ -747,21 +747,21 @@
 
 We could represent the integer ID in Opaleye as a `SqlInt4`
 
-> type BadWarehouseColumn = Warehouse' (Column SqlInt4)
->                                      (Column SqlText)
->                                      (Column SqlInt4)
+> type BadWarehouseField = Warehouse' (Field SqlInt4)
+>                                      (Field SqlText)
+>                                      (Field SqlInt4)
 >
-> badWarehouseTable :: Table BadWarehouseColumn BadWarehouseColumn
+> badWarehouseTable :: Table BadWarehouseField BadWarehouseField
 > badWarehouseTable = table "warehouse_table"
->         (pWarehouse Warehouse { wId       = tableColumn "id"
->                               , wLocation = tableColumn "location"
->                               , wNumGoods = tableColumn "num_goods" })
+>         (pWarehouse Warehouse { wId       = tableField "id"
+>                               , wLocation = tableField "location"
+>                               , wNumGoods = tableField "num_goods" })
 
 but that would expose us to the following sorts of errors, where we
 can meaninglessly relate the warehouse ID with the quantity of goods
 it holds.
 
-> badComparison :: BadWarehouseColumn -> Column SqlBool
+> badComparison :: BadWarehouseField -> Field SqlBool
 > badComparison w = wId w .== wNumGoods w
 
 On the other hand we can make a newtype for the warehouse ID
@@ -769,30 +769,30 @@
 > newtype WarehouseId' a = WarehouseId a
 > $(makeAdaptorAndInstance "pWarehouseId" ''WarehouseId')
 >
-> type WarehouseIdColumn = WarehouseId' (Column SqlInt4)
+> type WarehouseIdField = WarehouseId' (Field SqlInt4)
 >
-> type GoodWarehouseColumn = Warehouse' WarehouseIdColumn
->                                       (Column SqlText)
->                                       (Column SqlInt4)
+> type GoodWarehouseField = Warehouse' WarehouseIdField
+>                                       (Field SqlText)
+>                                       (Field SqlInt4)
 >
-> goodWarehouseTable :: Table GoodWarehouseColumn GoodWarehouseColumn
+> goodWarehouseTable :: Table GoodWarehouseField GoodWarehouseField
 > goodWarehouseTable = table "warehouse_table"
->         (pWarehouse Warehouse { wId       = pWarehouseId (WarehouseId (tableColumn "id"))
->                               , wLocation = tableColumn "location"
->                               , wNumGoods = tableColumn "num_goods" })
+>         (pWarehouse Warehouse { wId       = pWarehouseId (WarehouseId (tableField "id"))
+>                               , wLocation = tableField "location"
+>                               , wNumGoods = tableField "num_goods" })
 
 Now the comparison will not pass the type checker
 
-> -- forbiddenComparison :: GoodWarehouseColumn -> Column SqlBool
+> -- forbiddenComparison :: GoodWarehouseField -> Field SqlBool
 > -- forbiddenComparison w = wId w .== wNumGoods w
 > --
-> -- => Couldn't match type `WarehouseId' (Column SqlInt4)' with `Column SqlInt4'
+> -- => Couldn't match type `WarehouseId' (Field SqlInt4)' with `Field SqlInt4'
 
-but we can compare two `WarehouseIdColumn`s.
+but we can compare two `WarehouseIdField`s.
 
-> permittedComparison :: GoodWarehouseColumn
->                     -> GoodWarehouseColumn
->                     -> Column SqlBool
+> permittedComparison :: GoodWarehouseField
+>                     -> GoodWarehouseField
+>                     -> Field SqlBool
 > permittedComparison w1 w2 = wId w1 .=== wId w2
 
 (Currently we use `.===`, a more polymorphic version of `.==`, but
@@ -803,47 +803,47 @@
 
 
 Opaleye provides simple facilities for running queries on Postgres.
-`runQuery` is a typeclass polymorphic function that effectively has
+`runSelect` is a typeclass polymorphic function that effectively has
 the following type
 
-> -- runQuery :: Database.PostgreSQL.Simple.Connection
-> --          -> Query columns -> IO [haskells]
+> -- runSelect :: Database.PostgreSQL.Simple.Connection
+> --          -> Select columns -> IO [haskells]
 
 It converts a "record" of Opaleye columns to a list of "records" of
 Haskell values.  Like `leftJoin` this particular formulation uses
 typeclasses so please put type signatures on everything in sight to
 minimize the number of confusing error messages!
 
-For example, for the 'twentiesAtAddress' query `runQuery` would have
+For example, for the 'twentiesAtAddress' query `runSelect` would have
 the following type:
 
-> runTwentiesQuery :: PGS.Connection
->                  -> Query (Column SqlText, Column SqlInt4, Column SqlText)
+> runTwentiesSelect :: PGS.Connection
+>                  -> Select (Field SqlText, Field SqlInt4, Field SqlText)
 >                  -> IO [(String, Int, String)]
-> runTwentiesQuery = runQuery
+> runTwentiesSelect = runSelect
 
 Note that nullable columns are indicated with the Nullable type
 constructor, and these are converted to Maybe when executed.  If we
 have a table with a nullable column then Nullable columns turn into
-Maybes.  We could run the query `queryTable employeeTable` like this.
+Maybes.  We could run the query `selectTable employeeTable` like this.
 
-> runEmployeesQuery :: PGS.Connection
->                   -> Query (Column SqlText, Column (Nullable SqlText))
+> runEmployeesSelect :: PGS.Connection
+>                   -> Select (Field SqlText, FieldNullable SqlText)
 >                   -> IO [(String, Maybe String)]
-> runEmployeesQuery = runQuery
+> runEmployeesSelect = runSelect
 
 Newtypes are taken care of automatically by the typeclass instance
 that was generated by `makeAdaptorAndInstance`.  A `WarehouseId'
-(Column SqlInt4)` becomes a `WarehouseId' Int` when the query is run.
-We could run the query `queryTable goodWarehouseTable` like this.
+(Field SqlInt4)` becomes a `WarehouseId' Int` when the query is run.
+We could run the query `selectTable goodWarehouseTable` like this.
 
 > type WarehouseId = WarehouseId' Int
 > type GoodWarehouse = Warehouse' WarehouseId String Int
 >
-> runWarehouseQuery :: PGS.Connection
->                   -> Query GoodWarehouseColumn
+> runWarehouseSelect :: PGS.Connection
+>                   -> Select GoodWarehouseField
 >                   -> IO [GoodWarehouse]
-> runWarehouseQuery = runQuery
+> runWarehouseSelect = runSelect
 
 
 Conclusion
@@ -856,5 +856,5 @@
 
 This is a little utility function to help with printing generated SQL.
 
-> printSql :: Default Unpackspec a a => Query a -> IO ()
+> printSql :: Default Unpackspec a a => Select a -> IO ()
 > printSql = putStrLn . maybe "Empty query" id . showSqlForPostgres
diff --git a/Doc/Tutorial/TutorialBasicMonomorphic.lhs b/Doc/Tutorial/TutorialBasicMonomorphic.lhs
--- a/Doc/Tutorial/TutorialBasicMonomorphic.lhs
+++ b/Doc/Tutorial/TutorialBasicMonomorphic.lhs
@@ -6,12 +6,12 @@
 >
 > import           Prelude hiding (sum)
 >
-> import           Opaleye (Column, Nullable,
->                          Table, table, queryTable,
->                          tableColumn,
->                          Query, (.==),
+> import           Opaleye (Field, FieldNullable,
+>                          Table, table, selectTable,
+>                          tableField,
+>                          Select, (.==),
 >                          aggregate, groupBy,
->                          count, avg, sum, leftJoin, runQuery,
+>                          count, avg, sum, leftJoin, runSelect,
 >                          showSqlForPostgres, Unpackspec,
 >                          SqlInt4, SqlInt8, SqlText, SqlDate, SqlFloat8)
 >
@@ -61,23 +61,23 @@
 `Table` types will have the same type argument repeated twice.  In the
 manipulation tutorial you can see an example of when they might differ.
 
-> personTable :: Table (Column SqlText, Column SqlInt4, Column SqlText)
->                      (Column SqlText, Column SqlInt4, Column SqlText)
-> personTable = table "personTable" (p3 ( tableColumn "name"
->                                       , tableColumn "age"
->                                       , tableColumn "address" ))
+> personTable :: Table (Field SqlText, Field SqlInt4, Field SqlText)
+>                      (Field SqlText, Field SqlInt4, Field SqlText)
+> personTable = table "personTable" (p3 ( tableField "name"
+>                                       , tableField "age"
+>                                       , tableField "address" ))
 
-> personTable' :: Table (Column SqlText, Column SqlInt4, Column SqlText)
->                       (Column SqlText, Column SqlInt4, Column SqlText)
-> personTable' = table "personTable" (p3 ( tableColumn "name"
->                                        , tableColumn "age"
->                                        , tableColumn "address" ))
+> personTable' :: Table (Field SqlText, Field SqlInt4, Field SqlText)
+>                       (Field SqlText, Field SqlInt4, Field SqlText)
+> personTable' = table "personTable" (p3 ( tableField "name"
+>                                        , tableField "age"
+>                                        , tableField "address" ))
 
 By default, the table `"personTable"` is looked up in PostgreSQL's
 default `"public"` schema. If we wanted to specify a different schema we
 could have used the `tableWithSchema` constructor instead of `table`.
 
-To query a table we use `queryTable`.
+To query a table we use `selectTable`.
 
 (Here and in a few other places in Opaleye there is some typeclass
 magic going on behind the scenes to reduce boilerplate.  However, you
@@ -87,13 +87,13 @@
 because they are simpler to read and the typeclass magic is
 essentially invisible.)
 
-> personQuery :: Query (Column SqlText, Column SqlInt4, Column SqlText)
-> personQuery = queryTable personTable
+> personSelect :: Select (Field SqlText, Field SqlInt4, Field SqlText)
+> personSelect = selectTable personTable
 
-A `Query` corresponds to an SQL SELECT that we can run.  Here is the
-SQL generated for `personQuery`.
+A `Select` corresponds to an SQL SELECT that we can run.  Here is the
+SQL generated for `personSelect`.
 
-ghci> printSql personQuery
+ghci> printSql personSelect
 SELECT name0_1 as result1,
        age1_1 as result2,
        address2_1 as result3
@@ -132,22 +132,22 @@
 mean that you have to define more datatypes and more instances for
 them.
 
-> data BirthdayColumn = BirthdayColumn { bdNameColumn :: Column SqlText
->                                      , bdDayColumn  :: Column SqlDate }
+> data BirthdayField = BirthdayField { bdNameField :: Field SqlText
+>                                      , bdDayField  :: Field SqlDate }
 >
 > data Birthday = Birthday { bdName :: String, bdDay :: Day }
 >
-> birthdayColumnDef ::
->   (Applicative (p BirthdayColumn),
+> birthdayFieldDef ::
+>   (Applicative (p BirthdayField),
 >    P.Profunctor p,
->    Default p (Column SqlText) (Column SqlText),
->    Default p (Column SqlDate) (Column SqlDate)) =>
->   p BirthdayColumn BirthdayColumn
-> birthdayColumnDef = BirthdayColumn <$> P.lmap bdNameColumn D.def
->                                    <*> P.lmap bdDayColumn  D.def
+>    Default p (Field SqlText) (Field SqlText),
+>    Default p (Field SqlDate) (Field SqlDate)) =>
+>   p BirthdayField BirthdayField
+> birthdayFieldDef = BirthdayField <$> P.lmap bdNameField D.def
+>                                    <*> P.lmap bdDayField  D.def
 >
-> instance Default Unpackspec BirthdayColumn BirthdayColumn where
->   def = birthdayColumnDef
+> instance Default Unpackspec BirthdayField BirthdayField where
+>   def = birthdayFieldDef
 
 Naturally this is all derivable using `Generic` or Template Haskell,
 but no one's bothered to implement that yet.  Would you like to?
@@ -155,16 +155,16 @@
 Then we can use 'table' to make a table on our record type in exactly
 the same way as before.
 
-> birthdayTable :: Table BirthdayColumn BirthdayColumn
+> birthdayTable :: Table BirthdayField BirthdayField
 > birthdayTable =
 >   table "birthdayTable"
->   (BirthdayColumn <$> P.lmap bdNameColumn (tableColumn "name")
->                   <*> P.lmap bdDayColumn  (tableColumn "birthday"))
+>   (BirthdayField <$> P.lmap bdNameField (tableField "name")
+>                   <*> P.lmap bdDayField  (tableField "birthday"))
 >
-> birthdayQuery :: Query BirthdayColumn
-> birthdayQuery = queryTable birthdayTable
+> birthdaySelect :: Select BirthdayField
+> birthdaySelect = selectTable birthdayTable
 
-ghci> printSql birthdayQuery
+ghci> printSql birthdaySelect
 SELECT name0_1 as result1,
        birthday1_1 as result2
 FROM (SELECT *
@@ -192,15 +192,15 @@
 style, color, location, quantity and radius of widgets.  We can model
 this information with the following datatype.
 
-> data WidgetColumn = WidgetColumn { style    :: Column SqlText
->                                  , color    :: Column SqlText
->                                  , location :: Column SqlText
->                                  , quantity :: Column SqlInt4
->                                  , radius   :: Column SqlFloat8
+> data WidgetField = WidgetField { style    :: Field SqlText
+>                                  , color    :: Field SqlText
+>                                  , location :: Field SqlText
+>                                  , quantity :: Field SqlInt4
+>                                  , radius   :: Field SqlFloat8
 >                                  }
 >
-> instance Default Unpackspec WidgetColumn WidgetColumn where
->   def = WidgetColumn <$> P.lmap style    D.def
+> instance Default Unpackspec WidgetField WidgetField where
+>   def = WidgetField <$> P.lmap style    D.def
 >                      <*> P.lmap color    D.def
 >                      <*> P.lmap location D.def
 >                      <*> P.lmap quantity D.def
@@ -209,13 +209,13 @@
 For the purposes of this example the style, color and location will be
 strings, but in practice they might have been a different data type.
 
-> widgetTable :: Table WidgetColumn WidgetColumn
+> widgetTable :: Table WidgetField WidgetField
 > widgetTable = table "widgetTable"
->                      (WidgetColumn <$> P.lmap style    (tableColumn "style")
->                                    <*> P.lmap color    (tableColumn "color")
->                                    <*> P.lmap location (tableColumn "location")
->                                    <*> P.lmap quantity (tableColumn "quantity")
->                                    <*> P.lmap radius   (tableColumn "radius"))
+>                      (WidgetField <$> P.lmap style    (tableField "style")
+>                                    <*> P.lmap color    (tableField "color")
+>                                    <*> P.lmap location (tableField "location")
+>                                    <*> P.lmap quantity (tableField "quantity")
+>                                    <*> P.lmap radius   (tableField "radius"))
 
 
 Say we want to group by the style and color of widgets, calculating
@@ -223,14 +223,14 @@
 of such widgets and their average radius.  `aggregateWidgets` shows us
 how to do this.
 
-> aggregateWidgets :: Query (Column SqlText, Column SqlText, Column SqlInt8,
->                            Column SqlInt4, Column SqlFloat8)
+> aggregateWidgets :: Select (Field SqlText, Field SqlText, Field SqlInt8,
+>                            Field SqlInt4, Field SqlFloat8)
 > aggregateWidgets = aggregate ((,,,,) <$> P.lmap style    groupBy
 >                                      <*> P.lmap color    groupBy
 >                                      <*> P.lmap location count
 >                                      <*> P.lmap quantity sum
 >                                      <*> P.lmap radius   avg)
->                              (queryTable widgetTable)
+>                              (selectTable widgetTable)
 
 The generated SQL is
 
@@ -270,8 +270,8 @@
 uses of our Template Haskell derived code.  We use the 'pWidget'
 "adaptor" to specify how columns are aggregated.  Note that this is
 yet another example of avoiding a headache by keeping your datatype
-fully polymorphic, because the 'count' aggregator changes a 'Column
-String' into a 'Column Int64'.
+fully polymorphic, because the 'count' aggregator changes a 'Field
+String' into a 'Field Int64'.
 
 Outer join
 ==========
@@ -285,17 +285,17 @@
 nullability.  We introduce the following type synonym for this
 purpose, which is just a notational convenience.
 
-> data BirthdayColumnNullable =
->   BirthdayColumnNullable { bdNameColumnNullable :: Column (Nullable SqlText)
->                          , bdDayColumnNullable  :: Column (Nullable SqlDate) }
+> data BirthdayFieldNullable =
+>   BirthdayFieldNullable { bdNameFieldNullable :: FieldNullable SqlText
+>                          , bdDayFieldNullable  :: FieldNullable SqlDate }
 >
-> instance Default O.Unpackspec BirthdayColumnNullable BirthdayColumnNullable where
->   def = BirthdayColumnNullable <$> P.lmap bdNameColumnNullable D.def
->                                <*> P.lmap bdDayColumnNullable  D.def
+> instance Default O.Unpackspec BirthdayFieldNullable BirthdayFieldNullable where
+>   def = BirthdayFieldNullable <$> P.lmap bdNameFieldNullable D.def
+>                                <*> P.lmap bdDayFieldNullable  D.def
 >
-> instance Default Opaleye.Internal.Join.NullMaker BirthdayColumn BirthdayColumnNullable where
->   def = BirthdayColumnNullable <$> P.lmap bdNameColumn D.def
->                                <*> P.lmap bdDayColumn  D.def
+> instance Default Opaleye.Internal.Join.NullMaker BirthdayField BirthdayFieldNullable where
+>   def = BirthdayFieldNullable <$> P.lmap bdNameField D.def
+>                                <*> P.lmap bdDayField  D.def
 
 Again, this is all derivable using `Generic` or Template Haskell, if
 someone would take the time to implement it.
@@ -303,11 +303,11 @@
 A left join is expressed by specifying the two tables to join and the
 join condition.
 
-> personBirthdayLeftJoin :: Query ((Column SqlText, Column SqlInt4, Column SqlText),
->                                  BirthdayColumnNullable)
-> personBirthdayLeftJoin = leftJoin personQuery birthdayQuery eqName
+> personBirthdayLeftJoin :: Select ((Field SqlText, Field SqlInt4, Field SqlText),
+>                                  BirthdayFieldNullable)
+> personBirthdayLeftJoin = leftJoin personSelect birthdaySelect eqName
 >     where eqName ((name, _, _), birthdayRow) =
->             name .== bdNameColumn birthdayRow
+>             name .== bdNameField birthdayRow
 
 The generated SQL is
 
@@ -371,25 +371,25 @@
 
 
 Opaleye provides simple facilities for running queries on Postgres.
-`runQuery` is a typeclass polymorphic function that effectively has
+`runSelect` is a typeclass polymorphic function that effectively has
 the following type
 
-> -- runQuery :: Database.PostgreSQL.Simple.Connection
-> --          -> Query columns -> IO [haskells]
+> -- runSelect :: Database.PostgreSQL.Simple.Connection
+> --          -> Select fields -> IO [haskells]
 
 It converts a "record" of Opaleye columns to a list of "records" of
 Haskell values.  Like `leftJoin` this particular formulation uses
 typeclasses so please put type signatures on everything in sight to
 minimize the number of confusing error messages!
 
-> instance Default O.QueryRunner BirthdayColumn Birthday where
->   def = Birthday <$> P.lmap bdNameColumn D.def
->                  <*> P.lmap bdDayColumn  D.def
+> instance Default O.FromFields BirthdayField Birthday where
+>   def = Birthday <$> P.lmap bdNameField D.def
+>                  <*> P.lmap bdDayField  D.def
 >
-> runBirthdayQuery :: PGS.Connection
->                  -> Query BirthdayColumn
+> runBirthdaySelect :: PGS.Connection
+>                  -> Select BirthdayField
 >                  -> IO [Birthday]
-> runBirthdayQuery = runQuery
+> runBirthdaySelect = runSelect
 
 Again, this is derivable using `Generic` or Template Haskell, if
 someone would take the time to implement it.
@@ -404,5 +404,5 @@
 
 This is a little utility function to help with printing generated SQL.
 
-> printSql :: Default Unpackspec a a => Query a -> IO ()
+> printSql :: Default Unpackspec a a => Select a -> IO ()
 > printSql = putStrLn . maybe "Empty query" id . showSqlForPostgres
diff --git a/Doc/Tutorial/TutorialBasicTypeFamilies.lhs b/Doc/Tutorial/TutorialBasicTypeFamilies.lhs
--- a/Doc/Tutorial/TutorialBasicTypeFamilies.lhs
+++ b/Doc/Tutorial/TutorialBasicTypeFamilies.lhs
@@ -14,10 +14,10 @@
 >
 > import           Prelude hiding (sum)
 >
-> import           Opaleye (Column,
->                          Table, table, tableColumn, queryTable,
->                          Query, (.==), aggregate, groupBy,
->                          count, avg, sum, leftJoin, runQuery,
+> import           Opaleye (Field,
+>                          Table, table, tableField, selectTable,
+>                          Select, (.==), aggregate, groupBy,
+>                          count, avg, sum, leftJoin, runSelect, runSelectTF,
 >                          showSqlForPostgres, Unpackspec,
 >                          SqlInt4, SqlInt8, SqlText, SqlDate, SqlFloat8)
 >
@@ -67,17 +67,17 @@
 we can read from the table.  In this case all columns are required, so
 the write and read types will be the same.
 
-> personTable :: Table (Column SqlText, Column SqlInt4, Column SqlText)
->                      (Column SqlText, Column SqlInt4, Column SqlText)
-> personTable = table "personTable" (p3 ( tableColumn "name"
->                                       , tableColumn "age"
->                                       , tableColumn "address" ))
+> personTable :: Table (Field SqlText, Field SqlInt4, Field SqlText)
+>                      (Field SqlText, Field SqlInt4, Field SqlText)
+> personTable = table "personTable" (p3 ( tableField "name"
+>                                       , tableField "age"
+>                                       , tableField "address" ))
 
 By default, the table `"personTable"` is looked up in PostgreSQL's
 default `"public"` schema. If we wanted to specify a different schema we
 could have used the `tableWithSchema` function instead of `table`.
 
-To query a table we use `queryTable`.
+To query a table we use `selectTable`.
 
 (Here and in a few other places in Opaleye there is some typeclass
 magic going on behind the scenes to reduce boilerplate.  However, you
@@ -87,15 +87,15 @@
 because they are simpler to read and the typeclass magic is
 essentially invisible.)
 
-> personQuery :: Query (Column SqlText, Column SqlInt4, Column SqlText)
-> personQuery = queryTable personTable
+> personSelect :: Select (Field SqlText, Field SqlInt4, Field SqlText)
+> personSelect = selectTable personTable
 
-A `Query` corresponds to an SQL SELECT that we can run.  Here is the
-SQL generated for `personQuery`.  (`printSQL` is just a convenient
+A `Select` corresponds to an SQL SELECT that we can run.  Here is the
+SQL generated for `personSelect`.  (`printSQL` is just a convenient
 utility function for the purposes of this example file.  See below for
 its definition.)
 
-    ghci> printSql personQuery
+    ghci> printSql personSelect
     SELECT name0_1 as result1,
            age1_1 as result2,
            address2_1 as result3
@@ -131,10 +131,6 @@
 using type families that reduces boiler plate and has always been
 compatible with Opaleye!
 
-> -- Cryptic remark: If we were willing to only support 7.8 and up we
-> -- could even have a symbol field containing the table name and use
-> -- https://hackage.haskell.org/package/base-4.8.2.0/docs/GHC-TypeLits.html#v:symbolVal
-> 
 > data Birthday f = Birthday { bdName :: TableField f String SqlText NN Req
 >                            , bdDay  :: TableField f Day    SqlDate NN Req
 >                            }
@@ -164,14 +160,14 @@
 
 > birthdayTable :: Table (Birthday W) (Birthday O)
 > birthdayTable = table "birthdayTable" $ pBirthday $ Birthday {
->     bdName = tableColumn "name"
->   , bdDay  = tableColumn "birthday"
+>     bdName = tableField "name"
+>   , bdDay  = tableField "birthday"
 > }
 >
-> birthdayQuery :: Query (Birthday O)
-> birthdayQuery = queryTable birthdayTable
+> birthdaySelect :: Select (Birthday O)
+> birthdaySelect = selectTable birthdayTable
 
-    ghci> printSql birthdayQuery
+    ghci> printSql birthdaySelect
     SELECT name0_1 as result1,
            birthday1_1 as result2
     FROM (SELECT *
@@ -235,11 +231,11 @@
 
 > widgetTable :: Table (Widget W) (Widget O)
 > widgetTable = table "widgetTable" $ pWidget $ Widget {
->     style    = tableColumn "style"
->   , color    = tableColumn "color"
->   , location = tableColumn "location"
->   , quantity = tableColumn "quantity"
->   , radius   = tableColumn "radius"
+>     style    = tableField "style"
+>   , color    = tableField "color"
+>   , location = tableField "location"
+>   , quantity = tableField "quantity"
+>   , radius   = tableField "radius"
 > }
 
 Say we want to group by the style and color of widgets, calculating
@@ -247,14 +243,14 @@
 of such widgets and their average radius.  `aggregateWidgets` shows us
 how to do this.
 
-> aggregateWidgets :: Query (Column SqlText, Column SqlText, Column SqlInt8,
->                            Column SqlInt4, Column SqlFloat8)
+> aggregateWidgets :: Select (Field SqlText, Field SqlText, Field SqlInt8,
+>                            Field SqlInt4, Field SqlFloat8)
 > aggregateWidgets = aggregate ((,,,,) <$> P.lmap style    groupBy
 >                                      <*> P.lmap color    groupBy
 >                                      <*> P.lmap location count
 >                                      <*> P.lmap quantity sum
 >                                      <*> P.lmap radius   avg)
->                              (queryTable widgetTable)
+>                              (selectTable widgetTable)
 
 The generated SQL is
 
@@ -301,9 +297,9 @@
 outer joins).  An outer join is expressed by specifying the two tables
 to join and the join condition.
 
-> personBirthdayLeftJoin :: Query ((Column SqlText, Column SqlInt4, Column SqlText),
+> personBirthdayLeftJoin :: Select ((Field SqlText, Field SqlInt4, Field SqlText),
 >                                  Birthday Nulls)
-> personBirthdayLeftJoin = leftJoin personQuery birthdayQuery eqName
+> personBirthdayLeftJoin = leftJoin personSelect birthdaySelect eqName
 >     where eqName ((name, _, _), birthdayRow) = name .== bdName birthdayRow
 
 The generated SQL is
@@ -356,10 +352,10 @@
 
 > typeInferred =
 >     O.fullJoinInferrable (O.fullJoinInferrable
->                     birthdayQuery
->                     (queryTable widgetTable)
+>                     birthdaySelect
+>                     (selectTable widgetTable)
 >                     (const (O.pgBool True)))
->                birthdayQuery
+>                birthdaySelect
 >                (const (O.pgBool True))
 
 Running queries on Postgres
@@ -367,22 +363,28 @@
 
 
 Opaleye provides simple facilities for running queries on Postgres.
-`runQuery` is a typeclass polymorphic function that effectively has
+`runSelect` is a typeclass polymorphic function that effectively has
 the following type
 
-> -- runQuery :: Database.PostgreSQL.Simple.Connection
-> --          -> Query columns -> IO [haskells]
+> -- runSelect :: Database.PostgreSQL.Simple.Connection
+> --          -> Select columns -> IO [haskells]
 
 It converts a "record" of Opaleye columns to a list of "records" of
 Haskell values.  Like `leftJoin` this particular formulation uses
 typeclasses so please put type signatures on everything in sight to
 minimize the number of confusing error messages!
 
-> runBirthdayQuery :: PGS.Connection
->                  -> Query (Birthday O)
+> runBirthdaySelect :: PGS.Connection
+>                  -> Select (Birthday O)
 >                  -> IO [Birthday H]
-> runBirthdayQuery = runQuery
+> runBirthdaySelect = runSelect
 
+The type of selects can be inferred if you use the `runSelectTF`
+function.
+
+> -- printNames :: PGS.Connection -> Select (Birthday O) -> IO ()
+> printNames conn select = mapM_ (print . bdName) =<< runSelectTF conn select
+
 Conclusion
 ==========
 
@@ -393,5 +395,5 @@
 
 This is a little utility function to help with printing generated SQL.
 
-> printSql :: Default Unpackspec a a => Query a -> IO ()
+> printSql :: Default Unpackspec a a => Select a -> IO ()
 > printSql = putStrLn . maybe "Empty query" id . showSqlForPostgres
diff --git a/opaleye.cabal b/opaleye.cabal
--- a/opaleye.cabal
+++ b/opaleye.cabal
@@ -1,6 +1,6 @@
 name:            opaleye
 copyright:       Copyright (c) 2014-2018 Purely Agile Limited
-version:         0.6.7002.0
+version:         0.6.7003.0
 synopsis:        An SQL-generating DSL targeting PostgreSQL
 description:     An SQL-generating DSL targeting PostgreSQL.  Allows
                  Postgres queries to be written within Haskell in a
@@ -99,7 +99,7 @@
                    Opaleye.Internal.HaskellDB.Sql.Default,
                    Opaleye.Internal.HaskellDB.Sql.Generate,
                    Opaleye.Internal.HaskellDB.Sql.Print
-  ghc-options:     -Wall
+  ghc-options:     -Wall -Wcompat
 
 test-suite test
   default-language: Haskell2010
diff --git a/src/Opaleye.hs b/src/Opaleye.hs
--- a/src/Opaleye.hs
+++ b/src/Opaleye.hs
@@ -18,6 +18,7 @@
                , module Opaleye.Column
                , module Opaleye.Constant
                , module Opaleye.Distinct
+               , module Opaleye.Field
                , module Opaleye.FunctionalJoin
                , module Opaleye.Join
                , module Opaleye.Label
@@ -27,6 +28,7 @@
                , module Opaleye.PGTypes
                , module Opaleye.QueryArr
                , module Opaleye.RunQuery
+               , module Opaleye.RunSelect
                , module Opaleye.Sql
                , module Opaleye.Select
                , module Opaleye.SqlTypes
@@ -39,6 +41,13 @@
 import Opaleye.Column
 import Opaleye.Constant
 import Opaleye.Distinct
+import Opaleye.Field
+  hiding (null,
+          isNull,
+          matchNullable,
+          fromNullable,
+          toNullable,
+          maybeToNullable)
 import Opaleye.FunctionalJoin
 import Opaleye.Join
 import Opaleye.Label
@@ -48,6 +57,11 @@
 import Opaleye.PGTypes
 import Opaleye.QueryArr
 import Opaleye.RunQuery
+import Opaleye.RunSelect
+  hiding (foldForward,
+          closeCursor,
+          declareCursor,
+          declareCursorExplicit)
 import Opaleye.Select
 import Opaleye.Sql
 import Opaleye.SqlTypes
diff --git a/src/Opaleye/Internal/Table.hs b/src/Opaleye/Internal/Table.hs
--- a/src/Opaleye/Internal/Table.hs
+++ b/src/Opaleye/Internal/Table.hs
@@ -52,10 +52,10 @@
 -- The constructors of Table are internal only and will be
 -- deprecated in version 0.7.
 data Table writerColumns viewColumns
-  = Table String (TableColumns writerColumns viewColumns)
+  = Table String (TableFields writerColumns viewColumns)
     -- ^ For unqualified table names. Do not use the constructor.  It
     -- is internal and will be deprecated in version 0.7.
-  | TableWithSchema String String (TableColumns writerColumns viewColumns)
+  | TableWithSchema String String (TableFields writerColumns viewColumns)
     -- ^ Schema name, table name, table properties.  Do not use the
     -- constructor.  It is internal and will be deprecated in version 0.7.
 
@@ -63,29 +63,33 @@
 tableIdentifier (Table t _) = PQ.TableIdentifier Nothing t
 tableIdentifier (TableWithSchema s t _) = PQ.TableIdentifier (Just s) t
 
-tableColumns :: Table writeColumns viewColumns -> TableColumns writeColumns viewColumns
+tableColumns :: Table writeColumns viewColumns -> TableFields writeColumns viewColumns
 tableColumns (Table _ p) = p
 tableColumns (TableWithSchema _ _ p) = p
 
 -- | Use 'tableColumns' instead.  Will be deprecated soon.
-tableProperties :: Table writeColumns viewColumns -> TableColumns writeColumns viewColumns
+tableProperties :: Table writeColumns viewColumns -> TableFields writeColumns viewColumns
 tableProperties = tableColumns
 
--- | Use 'TableColumns' instead. 'TableProperties' will be deprecated
+-- | Use 'TableFields' instead. 'TableProperties' will be deprecated
 -- in version 0.7.
 data TableProperties writeColumns viewColumns = TableProperties
    { tablePropertiesWriter :: Writer writeColumns viewColumns
    , tablePropertiesView   :: View viewColumns }
 
--- | The new name for 'TableColumns' which will replace
--- 'TableColumn' in version 0.7.
+-- | Use 'TableFields' instead. 'TableColumns' will be deprecated in
+-- version 0.7.
 type TableColumns = TableProperties
 
-tableColumnsWriter :: TableColumns writeColumns viewColumns
+-- | The new name for 'TableColumns' and 'TableProperties' which will
+-- replace them in version 0.7.
+type TableFields = TableProperties
+
+tableColumnsWriter :: TableFields writeColumns viewColumns
                    -> Writer writeColumns viewColumns
 tableColumnsWriter = tablePropertiesWriter
 
-tableColumnsView :: TableColumns writeColumns viewColumns
+tableColumnsView :: TableFields writeColumns viewColumns
                  -> View viewColumns
 tableColumnsView = tablePropertiesView
 
@@ -111,14 +115,14 @@
 
 -- | 'required' is for columns which are not 'optional'.  You must
 -- provide them on writes.
-required :: String -> TableColumns (Column a) (Column a)
+required :: String -> TableFields (Column a) (Column a)
 required columnName = TableProperties
   (requiredW columnName)
   (View (Column (HPQ.BaseTableAttrExpr columnName)))
 
 -- | 'optional' is for columns that you can omit on writes, such as
 --  columns which have defaults or which are SERIAL.
-optional :: String -> TableColumns (Maybe (Column a)) (Column a)
+optional :: String -> TableFields (Maybe (Column a)) (Column a)
 optional columnName = TableProperties
   (optionalW columnName)
   (View (Column (HPQ.BaseTableAttrExpr columnName)))
@@ -128,7 +132,7 @@
     -- the write type.  It's generally more convenient to use this
     -- than 'required' or 'optional' but you do have to provide a type
     -- signature instead.
-    tableColumn :: String -> TableColumns writeType (Column sqlType)
+    tableColumn :: String -> TableFields writeType (Column sqlType)
 
 instance TableColumn (Column a) a where
     tableColumn = required
@@ -136,6 +140,10 @@
 instance TableColumn (Maybe (Column a)) a where
     tableColumn = optional
 
+tableField :: TableColumn writeType sqlType
+           => String -> TableFields writeType (Column sqlType)
+tableField = tableColumn
+
 queryTable :: U.Unpackspec viewColumns columns
             -> Table writeColumns viewColumns
             -> Tag.Tag
@@ -177,15 +185,15 @@
   where (outColumns, ()) = f extract columns
         extract (pes, s) = ((Zip (fmap return pes), [s]), ())
 
-data Zip a = Zip { unZip :: NEL.NonEmpty [a] }
+newtype Zip a = Zip { unZip :: NEL.NonEmpty [a] }
 
 instance Semigroup (Zip a) where
-  (<>) = mappend
+  Zip xs <> Zip ys = Zip (NEL.zipWith (++) xs ys)
 
 instance Monoid (Zip a) where
   mempty = Zip mempty'
     where mempty' = [] `NEL.cons` mempty'
-  Zip xs `mappend` Zip ys = Zip (NEL.zipWith (++) xs ys)
+  mappend = (<>)
 
 requiredW :: String -> Writer (Column a) (Column a)
 requiredW columnName =
diff --git a/src/Opaleye/RunSelect.hs b/src/Opaleye/RunSelect.hs
--- a/src/Opaleye/RunSelect.hs
+++ b/src/Opaleye/RunSelect.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE TypeFamilies #-}
 
 module Opaleye.RunSelect
@@ -18,6 +19,7 @@
 import qualified Opaleye.Select as S
 import qualified Opaleye.RunQuery          as RQ
 import qualified Opaleye.Sql as S
+import qualified Opaleye.TypeFamilies as TF
 import           Opaleye.Internal.RunQuery (FromFields)
 import qualified Opaleye.Internal.RunQuery as IRQ
 import qualified Opaleye.Internal.QueryArr as Q
@@ -51,6 +53,16 @@
           -- ^
           -> IO [haskells]
 runSelect = RQ.runQuery
+
+-- | 'runSelectTF' has better type inference than 'runSelect' but only
+-- works with "higher-kinded data" types.
+runSelectTF :: D.Default FromFields (rec TF.O) (rec TF.H)
+            => PGS.Connection
+            -- ^
+            -> S.Select (rec TF.O)
+            -- ^
+            -> IO [rec TF.H]
+runSelectTF = RQ.runQuery
 
 -- | @runSelectFold@ streams the results of a query incrementally and consumes
 -- the results with a left fold.
diff --git a/src/Opaleye/Table.hs b/src/Opaleye/Table.hs
--- a/src/Opaleye/Table.hs
+++ b/src/Opaleye/Table.hs
@@ -12,7 +12,7 @@
  'required' and gives rise to a
 
  @
- TableColumns (Column SqlInt4) (Column SqlInt4)
+ TableFields (Column SqlInt4) (Column SqlInt4)
  @
 
  The leftmost argument is the type of writes. When you insert or
@@ -23,7 +23,7 @@
  to a
 
  @
- TableColumns (Column (Nullable SqlInt4)) (Column (Nullable SqlInt4))
+ TableFields (Column (Nullable SqlInt4)) (Column (Nullable SqlInt4))
  @
 
  When you insert or update into this column you must give it a @Column
@@ -35,7 +35,7 @@
  rise to a
 
  @
- TableColumns (Maybe (Column SqlInt4)) (Column SqlInt4)
+ TableFields (Maybe (Column SqlInt4)) (Column SqlInt4)
  @
 
  Optional columns are those that can be omitted on writes, such as
@@ -49,7 +49,7 @@
  rise to a
 
  @
- TableColumns (Maybe (Column (Nullable SqlInt4))) (Column (Nullable SqlInt4))
+ TableFields (Maybe (Column (Nullable SqlInt4))) (Column (Nullable SqlInt4))
  @
 
  Optional columns are those that can be omitted on writes, such as
@@ -66,12 +66,14 @@
                       tableWithSchema,
                       T.Table,
                       T.tableColumn,
+                      T.tableField,
                       T.optional,
                       T.required,
                       -- * Querying tables
                       selectTable,
                       -- * Other
-                      TableColumns,
+                      T.TableColumns,
+                      TableFields,
                       -- * Deprecated
                       View,
                       Writer,
@@ -82,7 +84,7 @@
 import qualified Opaleye.Internal.QueryArr as Q
 import qualified Opaleye.Internal.Table as T
 import           Opaleye.Internal.Table (View, Table, Writer,
-                                         TableColumns)
+                                         TableFields)
 
 import qualified Opaleye.Internal.Tag as Tag
 import qualified Opaleye.Internal.Unpackspec as U
@@ -114,7 +116,7 @@
 -- | Create a table with unqualified names.
 table :: String
       -- ^ Table name
-      -> TableColumns writeFields viewFields
+      -> TableFields writeFields viewFields
       -> Table writeFields viewFields
 table = T.Table
 
@@ -123,7 +125,7 @@
                 -- ^ Schema name
                 -> String
                 -- ^ Table name
-                -> TableColumns writeFields viewFields
+                -> TableFields writeFields viewFields
                 -> Table writeFields viewFields
 tableWithSchema = T.TableWithSchema
 
