diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.6.3
+ 
+- Fix support for categorical column names that include spaces (@epn09)
+
 # 0.6.0
 Support external CSV tokenizers
 
diff --git a/Frames.cabal b/Frames.cabal
--- a/Frames.cabal
+++ b/Frames.cabal
@@ -1,5 +1,5 @@
 name:                Frames
-version:             0.6.2
+version:             0.6.3
 synopsis:            Data frames For working with tabular data files
 description:         User-friendly, type safe, runtime efficient tooling for
                      working with tabular data deserialized from
@@ -26,10 +26,11 @@
                      test/data/prestigePartial.csv
                      test/data/catSmall.csv test/data/catLarge.csv
                      test/data/multiline.csv
+                     test/data/issue145.csv
                      data/left1.csv data/right1.csv data/left_summary.csv
                      data/FL2.csv
 cabal-version:       >=1.10
-tested-with:         GHC == 8.4.4 || == 8.6.5 || == 8.8.2
+tested-with:         GHC == 8.4.4 || == 8.6.5 || == 8.8.3
 
 source-repository head
   type:     git
@@ -58,6 +59,7 @@
                        Frames.TypeLevel
                        Frames.Joins
                        Frames.ExtraInstances
+                       Frames.Utils
   other-extensions:    DataKinds, GADTs, KindSignatures, TypeFamilies,
                        TypeOperators, ConstraintKinds, StandaloneDeriving,
                        UndecidableInstances, ScopedTypeVariables,
@@ -227,7 +229,7 @@
   main-is:             Spec.hs
   other-modules:       DataCSV PrettyTH Temp LatinTest Issue114 NoHeader
                        UncurryFold UncurryFoldNoHeader UncurryFoldPartialData
-                       Categorical Chunks
+                       Categorical Chunks Issue145
   build-depends:       base, text, hspec, Frames, template-haskell,
                        temporary, directory, htoml, regex-applicative, pretty,
                        unordered-containers, pipes, HUnit, vinyl,
diff --git a/src/Frames/Categorical.hs b/src/Frames/Categorical.hs
--- a/src/Frames/Categorical.hs
+++ b/src/Frames/Categorical.hs
@@ -24,6 +24,7 @@
 import Frames.ColumnTypeable
 import Frames.InCore (VectorFor)
 import Frames.ShowCSV
+import Frames.Utils
 import GHC.Exts (Proxy#, proxy#)
 import GHC.TypeNats
 import Language.Haskell.TH
@@ -67,11 +68,11 @@
   ([ dataDecl, iIsString, iReadable, iParseable
    , iShowCSV, iVectorFor, iNFData ] ++)
   <$> unboxDecls name (length variants)
-  where variantCons = map (mkName . maybe id (++) prefix . cap) variants
+  where variantCons = map (mkName . T.unpack . sanitizeTypeName . T.pack . maybe id (++) prefix . cap) variants
         onVariants :: (String -> Name -> a) -> [a]
         onVariants f =
           getZipList (f <$> ZipList variants <*> ZipList variantCons)
-        nameName = mkName name
+        nameName = mkName . T.unpack . sanitizeTypeName . T.pack $ name
         fromStringClause variant variantCon =
           Clause [LitP (StringL variant)] (NormalB (ConE variantCon)) []
         showCSVClause variant variantCon =
diff --git a/src/Frames/TH.hs b/src/Frames/TH.hs
--- a/src/Frames/TH.hs
+++ b/src/Frames/TH.hs
@@ -6,8 +6,8 @@
 -- may be driven by an automated inference process or manual use of
 -- the individual helpers.
 module Frames.TH where
-import Control.Arrow (first, second)
-import Data.Char (isAlpha, isAlphaNum, toLower, toUpper)
+import Control.Arrow (second)
+import Data.Char (toLower)
 import Data.Maybe (fromMaybe)
 #if __GLASGOW_HASKELL__ < 804
 import Data.Semigroup ((<>))
@@ -21,6 +21,7 @@
 import Frames.ColumnUniverse
 import Frames.CSV
 import Frames.Rec(Record)
+import Frames.Utils
 import qualified GHC.Types as GHC
 import Language.Haskell.TH
 import Language.Haskell.TH.Syntax
@@ -33,25 +34,6 @@
 recDec = AppT (ConT ''Record) . go
   where go [] = PromotedNilT
         go (t:cs) = AppT (AppT PromotedConsT t) (go cs)
-
--- | Capitalize the first letter of a 'T.Text'.
-capitalize1 :: T.Text -> T.Text
-capitalize1 = foldMap (onHead toUpper) . T.split (not . isAlphaNum)
-  where onHead f = maybe mempty (uncurry T.cons . first f) . T.uncons
-
--- | Massage a column name from a CSV file into a valid Haskell type
--- identifier.
-sanitizeTypeName :: T.Text -> T.Text
-sanitizeTypeName = unreserved . fixupStart
-                 . T.concat . T.split (not . valid) . capitalize1
-  where valid c = isAlphaNum c || c == '\'' || c == '_'
-        unreserved t
-          | t `elem` ["Type", "Class"] = "Col" <> t
-          | otherwise = t
-        fixupStart t = case T.uncons t of
-                         Nothing -> "Col"
-                         Just (c,_) | isAlpha c -> t
-                                    | otherwise -> "Col" <> t
 
 -- | Declare a type synonym for a column.
 mkColSynDec :: TypeQ -> Name -> DecQ
diff --git a/src/Frames/Utils.hs b/src/Frames/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Frames/Utils.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE CPP, OverloadedStrings #-}
+module Frames.Utils (capitalize1, sanitizeTypeName) where
+
+import Control.Arrow (first)
+import Data.Char (isAlpha, isAlphaNum, toUpper)
+#if __GLASGOW_HASKELL__ < 804
+import Data.Semigroup ((<>))
+#endif
+import qualified Data.Text as T
+
+-- | Capitalize the first letter of a 'T.Text'.
+capitalize1 :: T.Text -> T.Text
+capitalize1 = foldMap (onHead toUpper) . T.split (not . isAlphaNum)
+  where onHead f = maybe mempty (uncurry T.cons . first f) . T.uncons
+
+-- | Massage a column name from a CSV file into a valid Haskell type
+-- identifier.
+sanitizeTypeName :: T.Text -> T.Text
+sanitizeTypeName = unreserved . fixupStart
+                 . T.concat . T.split (not . valid) . capitalize1
+  where valid c = isAlphaNum c || c == '\'' || c == '_'
+        unreserved t
+          | t `elem` ["Type", "Class"] = "Col" <> t
+          | otherwise = t
+        fixupStart t = case T.uncons t of
+                         Nothing -> "Col"
+                         Just (c,_) | isAlpha c -> t
+                                    | otherwise -> "Col" <> t
diff --git a/test/Issue145.hs b/test/Issue145.hs
new file mode 100644
--- /dev/null
+++ b/test/Issue145.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module Issue145 where
+
+import Frames.TH (RowGen (..), rowGenCat, tableTypes')
+
+tableTypes' (rowGenCat "test/data/issue145.csv") { rowTypeName = "Row", tablePrefix = "C" }
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -26,6 +26,7 @@
 
 import qualified LatinTest as Latin
 import qualified Issue114 as Issue114
+import qualified Issue145
 import qualified NoHeader
 import qualified Categorical
 
@@ -203,6 +204,10 @@
          mCustom <- H.runIO Categorical.fifthMonthCustom
          it "Can parse into manually-specified categorical variables" $
            mCustom `shouldBe` Just Categorical.MyMay
+         it "Can generate categorical types with space" $
+           enumFrom (minBound :: Issue145.RowCategoryName)
+             `shouldBe` [ Issue145.RowCategoryNameBarCategory
+                        , Issue145.RowCategoryNameFooCategory]
        describe "Detects parse failures" $ do
          caught <- H.runIO $
            (runSafeT $ do
diff --git a/test/data/issue145.csv b/test/data/issue145.csv
new file mode 100644
--- /dev/null
+++ b/test/data/issue145.csv
@@ -0,0 +1,3 @@
+id,category name
+1,foo category
+2,bar category
