diff --git a/System/Console/Haskeline/History.hs b/System/Console/Haskeline/History.hs
index 9fe2d126a14874e834a3b9549f161038d7ac7bda..f09e702fb0e09dbf09c3124189a5a45fd98eca0c 100644
--- a/System/Console/Haskeline/History.hs
+++ b/System/Console/Haskeline/History.hs
@@ -28,12 +28,17 @@ import qualified Data.Sequence as Seq
 import Data.Sequence ( Seq, (<|), ViewL(..), ViewR(..), viewl, viewr )
 import Data.Foldable (toList)
 
-import qualified Data.ByteString as B
-import qualified Data.ByteString.UTF8 as UTF8
 import Control.Exception
 
 import System.Directory(doesFileExist)
 
+#ifdef USE_GHC_ENCODINGS
+import qualified System.IO as IO
+#else
+import qualified Data.ByteString as B
+import qualified Data.ByteString.UTF8 as UTF8
+#endif
+
 data History = History {histLines :: Seq String,
                         stifleAmt :: Maybe Int}
                     -- stored in reverse
@@ -58,9 +63,7 @@ readHistory :: FilePath -> IO History
 readHistory file = handle (\(_::IOException) -> return emptyHistory) $ do
     exists <- doesFileExist file
     contents <- if exists
-        -- use binary file I/O to avoid Windows CRLF line endings
-        -- which cause confusion when switching between systems.
-        then fmap UTF8.toString (B.readFile file)
+        then readUTF8File file
         else return ""
     _ <- evaluate (length contents) -- force file closed
     return History {histLines = Seq.fromList $ lines contents,
@@ -70,7 +73,7 @@ readHistory file = handle (\(_::IOException) -> return emptyHistory) $ do
 -- error when writing the file, it will be ignored.
 writeHistory :: FilePath -> History -> IO ()
 writeHistory file = handle (\(_::IOException) -> return ())
-        . B.writeFile file . UTF8.fromString
+        . writeUTF8File file
         . unlines . historyLines 
 
 -- | Limit the number of lines stored in the history.
@@ -108,3 +111,38 @@ addHistoryRemovingAllDupes :: String -> History -> History
 addHistoryRemovingAllDupes h hs = addHistory h hs {histLines = filteredHS}
   where
     filteredHS = Seq.fromList $ filter (/= h) $ toList $ histLines hs
+
+---------
+-- UTF-8 file I/O, for old versions of GHC
+
+readUTF8File :: FilePath -> IO String
+#ifdef USE_GHC_ENCODINGS
+readUTF8File file = do
+    h <- IO.openFile file IO.ReadMode
+    IO.hSetEncoding h IO.utf8
+    IO.hSetNewlineMode h IO.noNewlineTranslation
+    contents <- IO.hGetContents h
+    _ <- evaluate (length contents)
+    IO.hClose h
+    return contents
+#else
+readUTF8File file = do
+    contents <- fmap UTF8.toString $ B.readFile file
+    _ <- evaluate (length contents)
+    return contents
+#endif
+
+writeUTF8File :: FilePath -> String -> IO ()
+#ifdef USE_GHC_ENCODINGS
+writeUTF8File file contents = do
+    h <- IO.openFile file IO.WriteMode
+    IO.hSetEncoding h IO.utf8
+    -- Write a file which is portable between systems.
+    IO.hSetNewlineMode h IO.noNewlineTranslation
+    IO.hPutStr h contents
+    IO.hClose h
+#else
+-- use binary file I/O to avoid Windows CRLF line endings
+-- which cause confusion when switching between systems.
+writeUTF8File file = B.writeFile file . UTF8.fromString
+#endif
diff --git a/haskeline.cabal b/haskeline.cabal
index 54a05e5eceea09bfcfc5d4e7e97f1c94bb563920..dd10632ed54c82786e4f5d02b1f9b0e66b803885 100644
--- a/haskeline.cabal
+++ b/haskeline.cabal
@@ -53,8 +53,7 @@ Library
         Build-depends: base>=3 && <4.1 , containers>=0.1 && < 0.3, directory==1.0.*,
                        bytestring==0.9.*
     }
-    Build-depends:  filepath >= 1.1 && < 1.4, mtl >= 1.1 && < 2.1,
-                    utf8-string==0.3.* && >=0.3.6
+    Build-depends:  filepath >= 1.1 && < 1.4, mtl >= 1.1 && < 2.1
     Extensions:     ForeignFunctionInterface, Rank2Types, FlexibleInstances,
                 TypeSynonymInstances
                 FlexibleContexts, ExistentialQuantification
@@ -90,6 +89,10 @@ Library
                 System.Console.Haskeline.Vi
     include-dirs: includes
     c-sources: cbits/h_wcwidth.c
+
+    if impl(ghc>=7.4) {
+        cpp-options: -DUSE_GHC_ENCODINGS
+    }
     if os(windows) {
         Build-depends: Win32>=2.0
         Other-modules: System.Console.Haskeline.Backend.Win32
@@ -98,8 +101,9 @@ Library
         install-includes: win_console.h
         cpp-options: -DMINGW
     } else {
-        Build-depends: unix>=2.0 && < 2.6
+        Build-depends: unix>=2.0 && < 2.6,
                         -- unix-2.3 doesn't build on ghc-6.8.1 or earlier
+                       utf8-string==0.3.* && >=0.3.6
         c-sources: cbits/h_iconv.c
         includes: h_iconv.h
         install-includes: h_iconv.h