diff --git a/ChangeLog b/ChangeLog
new file mode 100644
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,4 @@
+# 1.4.0
+
+* Switch to hashtables & hashable packages for GHC 7.8.1 compatibility.
+* No functional changes.
diff --git a/OpenAFP-Utils.cabal b/OpenAFP-Utils.cabal
--- a/OpenAFP-Utils.cabal
+++ b/OpenAFP-Utils.cabal
@@ -1,5 +1,5 @@
 Name:               OpenAFP-Utils
-Version:            1.3.1.2
+Version:            1.4.0
 License:            PublicDomain
 License-file:       LICENSE
 Author:             Audrey Tang
@@ -9,65 +9,66 @@
 Category:           Data
 Build-type:         Simple
 Cabal-Version:      >= 1.6
+extra-source-files: ChangeLog
 
 Executable afp2line2pdf
     Main-is:            afp2line2pdf.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5, line2pdf >= 0.0.7, bytestring
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5, line2pdf >= 0.0.7, bytestring
     Extensions:         StandaloneDeriving, GeneralizedNewtypeDeriving, ImplicitParams,
                         ExistentialQuantification, PatternGuards
 
 Executable afp-olndump
     Main-is:            afp-olndump.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5, bytestring, containers, binary
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5, bytestring, containers, binary
 
 Executable afp-dump
     Main-is:            afp-dump.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5, bytestring, containers, iconv, xhtml
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5, bytestring, containers, iconv, xhtml
     Extensions:         DeriveDataTypeable, PatternGuards
 
 Executable afp-page
     Main-is:            afp-page.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5
 
 Executable afp-replace
     Main-is:            afp-replace.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5
     Extensions:         DeriveDataTypeable, FlexibleContexts, PatternGuards
 
 Executable afp-scanudc
     Main-is:            afp-scanudc.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5, directory
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5, directory
     Extensions:         BangPatterns, PatternGuards
 
 Executable afp-split
     Main-is:            afp-split.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5
 
 Executable afp-split-scb
     Main-is:            afp-split-scb.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5
 
 Executable afp-split-tcb
     Main-is:            afp-split-tcb.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5, filepath
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5, filepath
     Extensions:         ImplicitParams
 
 Executable afp-type
     Main-is:            afp-type.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5
 
 Executable afp-udcfix
     Main-is:            afp-udcfix.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5, regex-base, regex-posix
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5, regex-base, regex-posix, hashable
     Extensions:         DeriveDataTypeable, MultiParamTypeClasses, FlexibleContexts, PatternGuards, RankNTypes
 
 Executable afp-validate
     Main-is:            afp-validate.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5
 
 Executable afp2line
     Main-is:            afp2line.hs
-    Build-depends:      OpenAFP >= 1.3, base >= 4 && < 5, containers
+    Build-depends:      OpenAFP >= 1.4, base >= 4 && < 5, containers
     Extensions:         GeneralizedNewtypeDeriving 
 
 source-repository head
diff --git a/afp-dump.hs b/afp-dump.hs
--- a/afp-dump.hs
+++ b/afp-dump.hs
@@ -6,7 +6,6 @@
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Lazy as L
 import qualified Data.ByteString.Char8 as C
-import qualified Data.HashTable as H
 
 -- The key here is inventing a ConcreteDataView for our data structure.
 -- See OpenAFP.Types.View for details.
@@ -134,21 +133,21 @@
     = li << (typeHtml t +++ fieldsHtml fs)
 
 {-# NOINLINE _TypeHtmlCache #-}
-_TypeHtmlCache :: H.HashTable RecordType Html 
-_TypeHtmlCache = unsafePerformIO $ H.new (==) (hashInt . typeInt)
+_TypeHtmlCache :: HashTable RecordType Html
+_TypeHtmlCache = unsafePerformIO hashCreate
 
 {-# NOINLINE _FontToEncoding #-}
 _FontToEncoding :: HashTable N1 Encoding
-_FontToEncoding = unsafePerformIO $ hashNew (==) fromIntegral
+_FontToEncoding = unsafePerformIO hashCreate
 
 typeHtml :: RecordType -> Html
 typeHtml t = unsafePerformIO $ do
-    rv <- H.lookup _TypeHtmlCache t
+    rv <- hashLookup _TypeHtmlCache t
     case rv of 
         Just html   -> return html
         _           -> do
             let html = typeHtml' t
-            H.insert _TypeHtmlCache t html
+            hashInsert _TypeHtmlCache t html
             return html
 
 typeHtml' :: RecordType -> Html
diff --git a/afp-udcfix.hs b/afp-udcfix.hs
--- a/afp-udcfix.hs
+++ b/afp-udcfix.hs
@@ -8,6 +8,7 @@
 import Data.Int
 import Text.Regex.Posix
 import Text.Regex.Base.RegexLike
+import Data.Hashable (Hashable(..))
 
 -- | Flags.
 type VarsIO a = StateIO Vars a
@@ -392,14 +393,16 @@
 type Config = Int
 
 data CacheKey = MkCacheKey
-    { ck_hash   :: !Int32
+    { ck_hash   :: !Int
     , ck_font   :: !ByteString
     }
     deriving Eq
+instance Hashable CacheKey where
+    hashWithSalt salt = hashWithSalt salt . ck_hash
 
 cacheKey :: ByteString -> NChar -> CacheKey
 cacheKey font (hi, lo) = MkCacheKey 
-    (hashString (chr (fromEnum hi) : chr (fromEnum lo) : C.unpack font))
+    (hash (fromEnum hi, fromEnum lo, font))
     font
 
 initVars :: IO Vars
@@ -414,8 +417,8 @@
     fid <- newIORef 0
     udc <- newIORef []
     idf <- newIOArray (0x00, 0xFF) C.empty
-    ifc <- hashNew (==) ck_hash
-    inc <- hashNew (==) ck_hash
+    ifc <- hashCreate
+    inc <- hashCreate
     opt <- getOpts
     return $ Vars xp x y xo yo im bi fid udc idf ifc inc opt
 
@@ -458,7 +461,7 @@
 
 {-# NOINLINE _ReaderCache #-}
 _ReaderCache :: HashTable ByteString [AFP_]
-_ReaderCache = unsafePerformIO (hashNew (==) hashByteString)
+_ReaderCache = unsafePerformIO hashCreate
 
 infixl 4 &:
 l &: v = do
diff --git a/afp2line.hs b/afp2line.hs
--- a/afp2line.hs
+++ b/afp2line.hs
@@ -115,7 +115,7 @@
 
 {-# NOINLINE _FontToEncoding #-}
 _FontToEncoding :: HashTable N1 Encoding
-_FontToEncoding = unsafePerformIO $ hashNew (==) fromIntegral
+_FontToEncoding = unsafePerformIO hashCreate
 
 -- | Record font Id to Name mappings in MCF's RLI and FQN chunks.
 mcfHandler :: MCF -> IO ()
diff --git a/afp2line2pdf.hs b/afp2line2pdf.hs
--- a/afp2line2pdf.hs
+++ b/afp2line2pdf.hs
@@ -234,7 +234,7 @@
 
 {-# NOINLINE _FontToEncoding #-}
 _FontToEncoding :: HashTable N1 Encoding
-_FontToEncoding = unsafePerformIO $ hashNew (==) fromIntegral
+_FontToEncoding = unsafePerformIO hashCreate
 
 -- | Record font Id to Name mappings in MCF's RLI and FQN chunks.
 mcfHandler :: MCF -> IO ()
