diff --git a/rdf4h.cabal b/rdf4h.cabal
--- a/rdf4h.cabal
+++ b/rdf4h.cabal
@@ -1,5 +1,5 @@
 name:            rdf4h
-version:         0.9.1
+version:         1.0.0
 synopsis:        A library for RDF processing in Haskell
 description:     
   'RDF for Haskell' is a library for working with RDF in Haskell.
@@ -39,25 +39,26 @@
                  , Data.RDF.Namespace
                  , Data.RDF.MGraph
                  , Data.RDF.TriplesGraph
-                 , Text.RDF.RDF4H.NTriplesParser
-                 , Text.RDF.RDF4H.NTriplesSerializer
                  , Text.RDF.RDF4H.TurtleParser
                  , Text.RDF.RDF4H.TurtleSerializer
+                 , Text.RDF.RDF4H.NTriplesParser
+                 , Text.RDF.RDF4H.NTriplesSerializer
                  , Text.RDF.RDF4H.XmlParser
   if flag(small_base)
     build-depends: base >= 3, bytestring, directory, containers
   else
     build-depends: base < 3
-  build-depends:   parsec >= 3 && < 3.2
-                 , network >= 2.2.0.0 && < 2.4
-                 , HTTP >= 4000.0.0 && < 4000.3
-                 , hxt >= 9.0.0 && < 9.2
-                 , MissingH >= 1.0.0 && < 1.2
+  build-depends:   parsec >= 3
+                 , network >= 2.2.0.0
+                 , HTTP >= 4000.0.0
+                 , hxt >= 9.0.0
+                 , MissingH >= 1.0.0
+                 , text
   other-modules:   Data.RDF.Utils
                  , Text.RDF.RDF4H.ParserUtils
                  , Text.RDF.RDF4H.Interact
   hs-source-dirs:  src
-  extensions:      BangPatterns RankNTypes MultiParamTypeClasses Arrows FlexibleContexts
+  extensions:      BangPatterns RankNTypes MultiParamTypeClasses Arrows FlexibleContexts OverloadedStrings
   ghc-options:     -Wall -fno-warn-name-shadowing -fno-warn-missing-signatures -funbox-strict-fields -fno-warn-unused-do-bind
 
 
@@ -68,13 +69,14 @@
   else
     build-depends: base >= 4 && < 6
   build-depends:   parsec >= 3
-                 , network >= 2.2.0.0 && < 2.4
-                 , HTTP >= 4000.0.0 && < 4000.3
-                 , hxt >= 9.0.0 && < 9.2
-                 , MissingH >= 1.0.0 && < 1.2
+                 , network >= 2.2.0.0
+                 , HTTP >= 4000.0.0
+                 , hxt >= 9.0.0
+                 , MissingH >= 1.0.0
                  , containers
+                 , text
   hs-source-dirs:  src
-  extensions:      BangPatterns RankNTypes ScopedTypeVariables MultiParamTypeClasses
+  extensions:      BangPatterns RankNTypes ScopedTypeVariables MultiParamTypeClasses OverloadedStrings
   ghc-options:     -Wall -fno-warn-name-shadowing -fno-warn-missing-signatures -funbox-strict-fields -fno-warn-unused-do-bind
 
 
@@ -82,20 +84,21 @@
   type:          exitcode-stdio-1.0
   main-is:       Test.hs
   ghc-options:   -Wall -fno-warn-name-shadowing -fno-warn-missing-signatures -funbox-strict-fields -fno-warn-unused-do-bind
-  extensions:    RankNTypes MultiParamTypeClasses Arrows FlexibleContexts
+  extensions:    RankNTypes MultiParamTypeClasses Arrows FlexibleContexts OverloadedStrings
   build-depends: base >= 4 && < 6
                , parsec >= 3
-               , test-framework >= 0.2.3 && < 0.7
-               , test-framework-quickcheck2 >= 0.2.12.2
+               , test-framework >= 0.2.3
+               , test-framework-quickcheck2
                , test-framework-hunit >= 0.2.7
-               , HTTP >= 4000.0.0 && < 4000.3
-               , network >= 2.2.0.0 && < 2.4
-               , QuickCheck >= 1.2.0.0 && < 2.5
-               , HUnit >= 1.2.2.1 && < 1.3
-               , MissingH >= 1.0.0 && < 1.2
+               , HTTP >= 4000.0.0
+               , network >= 2.2.0.0
+               , QuickCheck >= 1.2.0.0
+               , HUnit >= 1.2.2.1
+               , MissingH >= 1.0.0
                , bytestring
                , hxt
                , containers
+               , text
   other-modules: Data.RDF
                , Data.RDF.Namespace
                , Data.RDF.MGraph
diff --git a/src/Data/RDF.hs b/src/Data/RDF.hs
--- a/src/Data/RDF.hs
+++ b/src/Data/RDF.hs
@@ -27,17 +27,16 @@
   listSubjectsWithPredicate,listObjectsOfPredicate,
   Subject, Predicate, Object,
   ParseFailure(ParseFailure),
-  FastString(uniq,value),mkFastString,
-  s2b,b2s,unode,bnode,lnode,plainL,plainLL,typedL,
+  {- FastString(uniq,value),mkFastString, -}
+  s2t,t2s,unode,bnode,lnode,plainL,plainLL,typedL,
   View, view,
-  fromEither, maybeHead, removeDupes
+  fromEither, removeDupes
 )
 where
 
 import Data.RDF.Namespace
-import Data.RDF.Utils
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
+import Data.RDF.Utils ( s2t, t2s, canonicalize )
+import qualified Data.Text as T
 import Data.List
 import System.IO
 import Text.Printf
@@ -129,7 +128,7 @@
 
   -- |Parse RDF from the given bytestring, yielding a failure with error message or
   -- the resultant RDF.
-  parseString :: forall rdf. (RDF rdf) => p -> ByteString -> Either ParseFailure rdf
+  parseString :: forall rdf. (RDF rdf) => p -> T.Text -> Either ParseFailure rdf
 
   -- |Parse RDF from the local file with the given path, yielding a failure with error
   -- message or the resultant RDF in the IO monad.
@@ -192,12 +191,12 @@
   -- |An RDF URI reference. See
   -- <http://www.w3.org/TR/rdf-concepts/#section-Graph-URIref> for more
   -- information.
-  UNode !FastString
+  UNode !T.Text
 
   -- |An RDF blank node. See
   -- <http://www.w3.org/TR/rdf-concepts/#section-blank-nodes> for more
   -- information.
-  | BNode !FastString
+  | BNode !T.Text
 
   -- |An RDF blank node with an auto-generated identifier, as used in
   -- Turtle.
@@ -213,13 +212,13 @@
 
 -- |Return a URIRef node for the given bytetring URI.
 {-# INLINE unode #-}
-unode :: ByteString -> Node
-unode = UNode . mkFastString
+unode :: T.Text -> Node
+unode = UNode
 
 -- |Return a blank node using the given string identifier.
 {-# INLINE bnode #-}
-bnode :: ByteString ->  Node
-bnode = BNode . mkFastString
+bnode :: T.Text ->  Node
+bnode = BNode
 
 -- |Return a literal node using the given LValue.
 {-# INLINE lnode #-}
@@ -257,33 +256,33 @@
   -- control over the format of the literal bytestring that we store.
 
   -- |A plain (untyped) literal value in an unspecified language.
-  PlainL !ByteString
+  PlainL !T.Text
 
   -- |A plain (untyped) literal value with a language specifier.
-  | PlainLL !ByteString !ByteString
+  | PlainLL !T.Text !T.Text
 
   -- |A typed literal value consisting of the literal value and
   -- the URI of the datatype of the value, respectively.
-  | TypedL !ByteString  !FastString
+  | TypedL !T.Text  !T.Text
 
 -- ================================
 -- Constructor functions for LValue
 
 -- |Return a PlainL LValue for the given string value.
 {-# INLINE plainL #-}
-plainL :: ByteString -> LValue
+plainL :: T.Text -> LValue
 plainL =  PlainL
 
 -- |Return a PlainLL LValue for the given string value and language,
 -- respectively.
 {-# INLINE plainLL #-}
-plainLL :: ByteString -> ByteString -> LValue
+plainLL :: T.Text -> T.Text -> LValue
 plainLL = PlainLL
 
 -- |Return a TypedL LValue for the given string value and datatype URI,
 -- respectively.
 {-# INLINE typedL #-}
-typedL :: ByteString -> FastString -> LValue
+typedL :: T.Text -> T.Text -> LValue
 typedL val dtype = TypedL (canonicalize dtype val) dtype
 
 -- Constructor functions for LValue
@@ -291,7 +290,7 @@
 
 
 -- |The base URL of an RDF.
-newtype BaseUrl = BaseUrl ByteString
+newtype BaseUrl = BaseUrl T.Text
   deriving (Eq, Ord, Show)
 
 -- |A 'NodeSelector' is either a function that returns 'True'
@@ -313,8 +312,8 @@
 -- |A node is equal to another node if they are both the same type
 -- of node and if the field values are equal.
 instance Eq Node where
-  (UNode fs1)    ==  (UNode fs2)     =  uniq fs1 == uniq fs2
-  (BNode fs1)    ==  (BNode fs2)     =  uniq fs1 == uniq fs2
+  (UNode bs1)    ==  (UNode bs2)     =   bs1 ==  bs2
+  (BNode bs1)    ==  (BNode bs2)     =   bs1 ==  bs2
   (BNodeGen i1)  ==  (BNodeGen i2)   =  i1 == i2
   (LNode l1)     ==  (LNode l2)      =  l1 == l2
   _              ==  _               =  False
@@ -331,9 +330,9 @@
   compare = compareNode
 
 compareNode :: Node -> Node -> Ordering
-compareNode (UNode fs1)                      (UNode fs2)                      = compareFS fs1 fs2
+compareNode (UNode bs1)                      (UNode bs2)                      = compare bs1 bs2
 compareNode (UNode _)                        _                                = LT
-compareNode (BNode fs1)                      (BNode fs2)                      = compareFS fs1 fs2
+compareNode (BNode bs1)                      (BNode bs2)                      = compare bs1 bs2
 compareNode (BNode _)                        (UNode _)                        = GT
 compareNode (BNode _)                        _                                = LT
 compareNode (BNodeGen i1)                    (BNodeGen i2)                    = compare i1 i2
@@ -348,9 +347,9 @@
     GT -> GT
 compareNode (LNode (PlainLL _ _))            (LNode (PlainL _))               = GT
 compareNode (LNode (PlainLL _ _))            (LNode _)                        = LT
-compareNode (LNode (TypedL bs1 fs1))         (LNode (TypedL bs2 fs2))         =
-  case compare fs1 fs2 of
-    EQ -> compare bs1 bs2
+compareNode (LNode (TypedL bsType1 bs1))         (LNode (TypedL bsType2 bs2))         =
+  case compare bs1 bs2 of
+    EQ -> compare bsType1 bsType2
     LT -> LT
     GT -> GT
 compareNode (LNode (TypedL _ _))             (LNode _)                        = GT
@@ -378,7 +377,7 @@
 instance Eq LValue where
   (PlainL bs1)        ==  (PlainL bs2)        =  bs1 == bs2
   (PlainLL bs1 bs1')  ==  (PlainLL bs2 bs2')  =  bs1' == bs2'    &&  bs1 == bs2
-  (TypedL bs1 fs1)    ==  (TypedL bs2 fs2)    =  equalFS fs1 fs2 &&  bs1 == bs2
+  (TypedL bsType1 bs1)    ==  (TypedL bsType2 bs2)    =  bsType1 == bsType2 &&  bs1 == bs2
   _                   ==  _                   =  False
 
 -- |Ordering of 'LValue' values is as follows: (PlainL _) < (PlainLL _ _)
@@ -402,7 +401,7 @@
 compareLValue (PlainLL _ _)       _                 = LT
 compareLValue _                   (PlainLL _ _)     = GT
 compareLValue (TypedL l1 t1) (TypedL l2 t2) =
-  case compareFS t1 t2 of
+  case compare t1 t2 of
     EQ -> compare l1 l2
     GT -> GT
     LT -> LT
@@ -420,9 +419,9 @@
   show (LNode lvalue)                = "LNode(" ++ show lvalue ++ ")"
 
 instance Show LValue where
-  show (PlainL lit)               = "PlainL(" ++ B.unpack lit ++ ")"
-  show (PlainLL lit lang)         = "PlainLL(" ++ B.unpack lit ++ ", " ++ B.unpack lang ++ ")"
-  show (TypedL lit dtype)         = "TypedL(" ++ B.unpack lit ++ "," ++ show dtype ++ ")"
+  show (PlainL lit)               = "PlainL(" ++ T.unpack lit ++ ")"
+  show (PlainLL lit lang)         = "PlainLL(" ++ T.unpack lit ++ ", " ++ T.unpack lang ++ ")"
+  show (TypedL lit dtype)         = "TypedL(" ++ T.unpack lit ++ "," ++ show dtype ++ ")"
 
 -- |Answer the given list of triples in sorted order.
 sortTriples :: Triples -> Triples
diff --git a/src/Data/RDF/Namespace.hs b/src/Data/RDF/Namespace.hs
--- a/src/Data/RDF/Namespace.hs
+++ b/src/Data/RDF/Namespace.hs
@@ -14,13 +14,11 @@
 )
 where
 
-import Data.RDF.Utils
 import Text.Printf
 import Data.Map(Map)
 import qualified Data.Map as Map
 import qualified Data.List as List
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
+import qualified Data.Text as T
 
 standard_namespaces :: [Namespace]
 standard_namespaces = [rdf, rdfs, dc, dct, owl, xsd, skos, foaf, ex, ex2]
@@ -71,7 +69,7 @@
 ex2   =   mkPrefixedNS'  "ex2"   "http://www2.example.org/"
 
 -- |An alias for a map from prefix to namespace URI.
-newtype PrefixMappings   = PrefixMappings (Map ByteString ByteString)
+newtype PrefixMappings   = PrefixMappings (Map T.Text T.Text)
   deriving (Eq, Ord)
 instance Show PrefixMappings where
   -- This is really inefficient, but it's not used much so not what
@@ -87,38 +85,38 @@
 
 -- |View the prefix mappings as a list of key-value pairs. The PM in
 -- in the name is to reduce name clashes if used without qualifying.
-toPMList :: PrefixMappings -> [(ByteString, ByteString)]
+toPMList :: PrefixMappings -> [(T.Text, T.Text)]
 toPMList (PrefixMappings m) = Map.toList m
 
 -- |A mapping of a prefix to the URI for that prefix.
-newtype PrefixMapping = PrefixMapping (ByteString, ByteString)
+newtype PrefixMapping = PrefixMapping (T.Text, T.Text)
   deriving (Eq, Ord)
 instance Show PrefixMapping where
-  show (PrefixMapping (prefix, uri)) = printf "PrefixMapping (%s, %s)" (b2s prefix) (b2s uri)
+  show (PrefixMapping (prefix, uri)) = printf "PrefixMapping (%s, %s)" (show prefix) (show uri)
 
 -- |Make a URI consisting of the given namespace and the given localname.
-mkUri :: Namespace -> ByteString -> ByteString
-mkUri ns local = uriOf ns `B.append` local
+mkUri :: Namespace -> T.Text -> T.Text
+mkUri ns local = uriOf ns `T.append` local
 
 -- |Represents a namespace as either a prefix and uri, respectively,
 --  or just a uri.
-data Namespace = PrefixedNS  ByteString ByteString -- prefix and ns uri
-               | PlainNS     ByteString            -- ns uri alone
+data Namespace = PrefixedNS  T.Text T.Text -- prefix and ns uri
+               | PlainNS     T.Text            -- ns uri alone
 
 -- |Make a namespace for the given URI reference.
-mkPlainNS     ::  ByteString -> Namespace
+mkPlainNS     ::  T.Text -> Namespace
 mkPlainNS       =  PlainNS
 
 -- |Make a namespace having the given prefix for the given URI reference,
 -- respectively.
-mkPrefixedNS  :: ByteString -> ByteString -> Namespace
+mkPrefixedNS  :: T.Text -> T.Text -> Namespace
 mkPrefixedNS    =  PrefixedNS
 
 -- |Make a namespace having the given prefix for the given URI reference,
 -- respectively, using strings which will be converted to bytestrings
 -- automatically.
 mkPrefixedNS' :: String -> String -> Namespace
-mkPrefixedNS' s1 s2 = mkPrefixedNS (B.pack s1) (B.pack s2)
+mkPrefixedNS' s1 s2 = mkPrefixedNS (T.pack s1) (T.pack s2)
 
 instance Eq Namespace where
   (PrefixedNS _ u1) == (PrefixedNS _ u2)  = u1 == u2
@@ -127,15 +125,15 @@
   (PlainNS      u1) == (PrefixedNS _ u2)  = u1 == u2
 
 instance Show Namespace where
-  show (PlainNS           uri)  =  B.unpack uri
-  show (PrefixedNS prefix uri)  =  printf "(PrefixNS %s %s)" (B.unpack prefix) (B.unpack uri)
+  show (PlainNS           uri)  =  T.unpack uri
+  show (PrefixedNS prefix uri)  =  printf "(PrefixNS %s %s)" (T.unpack prefix) (T.unpack uri)
 
 -- |Determine the URI of the given namespace.
-uriOf     ::  Namespace -> ByteString
+uriOf     ::  Namespace -> T.Text
 uriOf    (PlainNS      uri)  = uri
 uriOf    (PrefixedNS _ uri)  = uri
 
 -- |Determine the prefix of the given namespace, if it has one.
-prefixOf  ::  Namespace -> Maybe ByteString
+prefixOf  ::  Namespace -> Maybe T.Text
 prefixOf (PlainNS      _)    = Nothing
 prefixOf (PrefixedNS p _)    = Just p
diff --git a/src/Data/RDF/TriplesGraph.hs b/src/Data/RDF/TriplesGraph.hs
--- a/src/Data/RDF/TriplesGraph.hs
+++ b/src/Data/RDF/TriplesGraph.hs
@@ -47,6 +47,9 @@
   select            = select'
   query             = query'
 
+instance Show TriplesGraph where
+  show gr = concatMap (\t -> show t ++ "\n")  (triplesOf gr)
+
 prefixMappings' :: TriplesGraph -> PrefixMappings
 prefixMappings' (TriplesGraph (_, _, pms)) = pms
 
diff --git a/src/Data/RDF/Utils.hs b/src/Data/RDF/Utils.hs
--- a/src/Data/RDF/Utils.hs
+++ b/src/Data/RDF/Utils.hs
@@ -1,141 +1,44 @@
-{-#  OPTIONS_GHC -fno-cse  #-}
+
 module Data.RDF.Utils (
-  FastString(uniq, value),
-  mkFastString, equalFS, compareFS,
-  s2b, b2s, hPutStrRev, hPutStrLnRev,
-  canonicalize, maybeHead
+  t2s, s2t, hPutStrRev, canonicalize
 ) where
 
-import qualified Data.ByteString.Lazy as BL
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
+import qualified Data.Text as T
+import Data.Text.Encoding (encodeUtf8)
+import qualified Data.ByteString as B
 import Data.Map(Map)
 import qualified Data.Map as Map
 import System.IO
-import Data.IORef
-import System.IO.Unsafe(unsafePerformIO)
 
-bs_newline :: ByteString
-bs_newline = B.pack "\n"
-
--- |A safe version of head that returns 'Nothing' for an empty list or 'Just (head lst)' for
--- a non-empty list.
-maybeHead :: [a] -> Maybe a
-maybeHead lst | null lst   =  Nothing
-              | otherwise  =  Just (head lst)
-
--- |'FastString' is a bytestring-based string type that provides constant-time equality
--- testing.
---
--- A 'FastString' value consists of a unique identifier and a (strict) 'ByteString' value.
--- The unique identifier is used for constant-time equality testing, and all other operations
--- are provided by the 'ByteString' value itself.
---
--- 'FastString' values are created by the 'mkFastString' function, which maintains a table
--- of all created values, and reuses old values whenever possible. The 'ByteString' is
--- maintained internally in reverse order of the string passed to 'mkFastString'; this
--- is to provide faster comparison testing for unequal values, since it is very common in
--- RDF to have URIs that are equal apart from the last few characters (localname).
-data FastString = FS {
-      uniq   :: !Int,
-      value  :: !ByteString
-}
-
-instance Show FastString where
-  show = B.unpack . B.reverse . value
-
--- |Two 'FastString' values are equal iff they have the same unique identifer.
-instance Eq FastString where
-  (==) = equalFS
-
-{-# INLINE equalFS #-}
-equalFS :: FastString -> FastString -> Bool
-equalFS fs1 fs2 = uniq fs1 == uniq fs2
-
-
--- |Two 'FastString' values are equal if they have the same unique identifier,
--- and are otherwise ordered using the natural ordering of 'ByteString' in the
--- internal (reversed) representation.
-instance Ord FastString where
-  compare = compareFS
-
-{-# INLINE compareFS #-}
-compareFS :: FastString -> FastString -> Ordering
-compareFS fs1 fs2 =
-  if uniq fs1 == uniq fs2 then EQ else
-    compare (value fs1) (value fs2)
-
 -- |A convenience function for converting from a bytestring to a string.
-{-# INLINE b2s #-}
-b2s :: ByteString -> String
-b2s = B.unpack
+{-# INLINE t2s #-}
+t2s :: T.Text -> String
+t2s = T.unpack
 
 -- |A convenience function for converting from a string to a bytestring.
-{-# INLINE s2b #-}
-s2b :: String -> ByteString
-s2b = B.pack
+{-# INLINE s2t #-}
+s2t :: String -> T.Text
+s2t = T.pack
 
 -- |Write to the handle the reversed value of the bytestring, with no newline.
 {-# INLINE hPutStrRev #-}
-hPutStrRev :: Handle -> ByteString -> IO ()
-hPutStrRev h bs = BL.hPutStr h (B.reverse bs)
-
--- |Write to the handle the reversed value of the bytestring, followed by
--- a newline.
-{-# INLINE hPutStrLnRev #-}
-hPutStrLnRev :: Handle -> ByteString -> IO ()
-hPutStrLnRev h bs = BL.hPutStr h (B.reverse bs) >> BL.hPutStr h bs_newline
-
--- |Return a 'FastString' value for the given 'ByteString', reusing a 'FastString'
--- if one has been created for equal bytestrings, or creating a new one if necessary.
--- The 'FastString' values created maintain the invariant that two values have the
--- same unique identifier (accessible via 'uniq') iff their respective bytestring
--- values are equal.
---
--- The unique identifier is only for the given session, and equal 'ByteString' values
--- will generally not be assigned the same identifier under different processes and
--- different executions.
-{-# NOINLINE mkFastString #-}
-mkFastString :: ByteString -> FastString
-mkFastString bs =
-  unsafePerformIO $
-  do m <- readIORef fsMap
-     let mFs = Map.lookup bs m
-     case mFs of
-       Just fs  -> return fs
-       Nothing  -> newFastString bs >>= \fs ->
-                     writeIORef fsMap (Map.insert bs fs m) >>
-                     return fs
+hPutStrRev :: Handle -> T.Text -> IO ()
+hPutStrRev h bs = B.hPutStr h ((encodeUtf8 . T.reverse) bs)
 
--- |Canonicalize the given 'ByteString' value using the 'FastString'
+-- |Canonicalize the given 'T.Text' value using the 'FastString'
 -- as the datatype URI.
 {-# NOINLINE canonicalize #-}
-canonicalize :: FastString -> ByteString -> ByteString
+canonicalize :: T.Text -> T.Text -> T.Text
 canonicalize typeFs litValue =
   case Map.lookup typeFs canonicalizerTable of
     Nothing   ->  litValue
     Just fn   ->  fn litValue
 
-{-# INLINE newFastString #-}
-newFastString ::  ByteString -> IO FastString
-newFastString str =
-  do curr <- readIORef fsCounter
-     modifyIORef fsCounter (+1)
-     return $! FS curr (B.reverse str)
-
-{-# NOINLINE fsCounter #-}
-fsCounter :: IORef Int
-fsCounter = unsafePerformIO $ newIORef 0
-
-{-# NOINLINE fsMap #-}
-fsMap :: IORef (Map ByteString FastString)
-fsMap = unsafePerformIO $ newIORef Map.empty
-
 -- A table of mappings from a FastString URI (reversed as
--- they are) to a function that canonicalizes a ByteString
+-- they are) to a function that canonicalizes a T.Text
 -- assumed to be of that type.
 {-# NOINLINE canonicalizerTable #-}
-canonicalizerTable :: Map FastString (ByteString -> ByteString)
+canonicalizerTable :: Map T.Text (T.Text -> T.Text)
 canonicalizerTable =
   Map.fromList [(integerUri, _integerStr), (doubleUri, _doubleStr),
                 (decimalUri, _decimalStr)]
@@ -143,19 +46,19 @@
     integerUri = mkFsUri "http://www.w3.org/2001/XMLSchema#integer"
     decimalUri = mkFsUri "http://www.w3.org/2001/XMLSchema#decimal"
     doubleUri  = mkFsUri "http://www.w3.org/2001/XMLSchema#double"
-    mkFsUri :: String -> FastString
-    mkFsUri uri = mkFastString . s2b $! uri
+    mkFsUri :: String -> T.Text
+    mkFsUri uri = s2t $! uri
 
-_integerStr, _decimalStr, _doubleStr :: ByteString -> ByteString
-_integerStr = B.dropWhile (== '0')
+_integerStr, _decimalStr, _doubleStr :: T.Text -> T.Text
+_integerStr = T.dropWhile (== '0')
 
 -- exponent: [eE] ('-' | '+')? [0-9]+
 -- ('-' | '+') ? ( [0-9]+ '.' [0-9]* exponent | '.' ([0-9])+ exponent | ([0-9])+ exponent )
-_doubleStr s = B.pack $ show (read $ B.unpack s :: Double)
+_doubleStr s = T.pack $ show (read $ T.unpack s :: Double)
 
 -- ('-' | '+')? ( [0-9]+ '.' [0-9]* | '.' ([0-9])+ | ([0-9])+ )
 _decimalStr s =     -- haskell double parser doesn't handle '1.'..,
-  case B.last s of   -- so we add a zero if that's the case and then parse
-    '.' -> f (s `B.snoc` '0')
+  case T.last s of   -- so we add a zero if that's the case and then parse
+    '.' -> f (s `T.snoc` '0')
     _   -> f s
-  where f s' = B.pack $ show (read $ B.unpack s' :: Double)
+  where f s' = T.pack $ show (read $ T.unpack s' :: Double)
diff --git a/src/Rdf4hParseMain.hs b/src/Rdf4hParseMain.hs
--- a/src/Rdf4hParseMain.hs
+++ b/src/Rdf4hParseMain.hs
@@ -8,8 +8,8 @@
 import Text.RDF.RDF4H.TurtleParser
 import Text.RDF.RDF4H.TurtleSerializer
 
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
 
 import System.Environment
 import System.IO
@@ -55,10 +55,10 @@
           >> hPrintf stderr "OUTPUT-BASE-URI:  %s\n\n" outputBaseUri)
      let mInputUri
            = if inputBaseUri == "-" then Nothing else
-               Just (BaseUrl $ s2b inputBaseUri)
-         docUri = Just $ s2b inputUri
+               Just (BaseUrl (T.pack inputBaseUri))
+         docUri = Just $ T.pack inputUri
          emptyPms = PrefixMappings Map.empty
-     case (inputFormat, isUri $ s2b inputUri) of
+     case (inputFormat, isUri $ T.pack inputUri) of
          ("turtle", True) -> parseURL (TurtleParser mInputUri docUri)
                                inputUri
                                >>=
@@ -66,7 +66,7 @@
                                  write outputFormat docUri emptyPms res
          ("turtle", False) -> (if inputUri /= "-" then
                                  parseFile (TurtleParser mInputUri docUri) inputUri else
-                                 liftM (parseString (TurtleParser mInputUri docUri)) B.getContents)
+                                 liftM (parseString (TurtleParser mInputUri docUri)) TIO.getContents)
                                 >>=
                                 \ (res :: Either ParseFailure TriplesGraph) ->
                                   write outputFormat docUri emptyPms res
@@ -75,13 +75,13 @@
                                    write outputFormat Nothing emptyPms res
          ("ntriples", False) -> (if inputUri /= "-" then
                                    parseFile NTriplesParser inputUri else
-                                   liftM (parseString NTriplesParser) B.getContents)
+                                   liftM (parseString NTriplesParser) TIO.getContents)
                                   >>=
                                   \ (res :: Either ParseFailure TriplesGraph) ->
                                     write outputFormat Nothing emptyPms res
          (str, _) -> putStrLn ("Invalid format: " ++ str) >> exitFailure
 
-write :: forall rdf. (RDF rdf) => String -> Maybe ByteString -> PrefixMappings -> Either ParseFailure rdf -> IO ()
+write :: forall rdf. (RDF rdf) => String -> Maybe T.Text -> PrefixMappings -> Either ParseFailure rdf -> IO ()
 write format docUri pms res =
   case res of
     (Left (ParseFailure msg)) -> putStrLn msg >> exitWith (ExitFailure 1)
@@ -106,9 +106,9 @@
 
 -- Determine if the bytestring represents a URI, which is currently
 -- decided solely by checking for a colon in the string.
-isUri :: ByteString -> Bool
-isUri str = not (B.null post) && B.all isLetter pre
-  where (pre, post) = B.break (== ':') str
+isUri :: T.Text -> Bool
+isUri str = not (T.null post) && T.all isLetter pre
+  where (pre, post) = T.break (== ':') str
 
 -- Extract from the list of flags a flag of the same type as the first
 -- flag argument, returning its string value; if there is no such flag,
diff --git a/src/Text/RDF/RDF4H/Interact.hs b/src/Text/RDF/RDF4H/Interact.hs
--- a/src/Text/RDF/RDF4H/Interact.hs
+++ b/src/Text/RDF/RDF4H/Interact.hs
@@ -14,8 +14,7 @@
 
 module Text.RDF.RDF4H.Interact where
 
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
+import qualified Data.Text as T
 
 import Data.RDF
 import Data.RDF.Utils()
@@ -40,13 +39,13 @@
 loadTurtleURL  :: forall rdf. (RDF rdf) => Maybe String -> Maybe String -> String -> IO rdf
 loadTurtleURL baseUrl docUri  = _load parseURL (mkTurtleParser baseUrl docUri)
 
--- |Parse a Turtle document from the given 'ByteString' using the given @baseUrl@ and 
+-- |Parse a Turtle document from the given 'T.Text' using the given @baseUrl@ and 
 -- @docUri@, which have the same semantics as in the loadTurtle* functions.
-parseTurtleString :: forall rdf. (RDF rdf) => Maybe String -> Maybe String -> ByteString -> rdf
+parseTurtleString :: forall rdf. (RDF rdf) => Maybe String -> Maybe String -> T.Text -> rdf
 parseTurtleString baseUrl docUri = _parse parseString (mkTurtleParser baseUrl docUri)
 
 mkTurtleParser :: Maybe String -> Maybe String -> TurtleParser
-mkTurtleParser b d = TurtleParser ((BaseUrl . B.pack) `fmap` b) (B.pack `fmap` d)
+mkTurtleParser b d = TurtleParser ((BaseUrl . T.pack) `fmap` b) (T.pack `fmap` d)
 
 -- |Load an NTriples file from the filesystem.
 -- 
@@ -59,11 +58,12 @@
 loadNTriplesURL :: forall rdf. (RDF rdf) => String -> IO rdf
 loadNTriplesURL  = _load parseURL  NTriplesParser
 
--- |Parse an NTriples document from the given 'ByteString', as 'loadNTriplesFile' does
+-- |Parse an NTriples document from the given 'T.Text', as 'loadNTriplesFile' does
 -- from a file.
-parseNTriplesString :: forall rdf. (RDF rdf) => ByteString -> rdf
+parseNTriplesString :: forall rdf. (RDF rdf) => T.Text -> rdf
 parseNTriplesString = _parse parseString NTriplesParser
 
+
 -- |Print a list of triples to stdout; useful for debugging and interactive use.
 printTriples :: Triples -> IO ()
 printTriples  = mapM_ print
@@ -76,11 +76,11 @@
              p -> String -> IO rdf
 _load parseFunc parser location = parseFunc parser location >>= _handle
 
--- Use the given parseFunc and parser to parse the given 'ByteString', calling error
+-- Use the given parseFunc and parser to parse the given 'T.Text', calling error
 -- with the 'ParseFailure' message if unable to load or parse for any reason.
 _parse :: forall p rdf. (RdfParser p, RDF rdf) => 
-                        (p -> ByteString -> Either ParseFailure rdf) -> 
-                         p -> ByteString -> rdf
+                        (p -> T.Text -> Either ParseFailure rdf) -> 
+                         p -> T.Text -> rdf
 _parse parseFunc parser rdfBs = either (error . show) id $ parseFunc parser rdfBs
 
 -- Handle the result of an IO parse by returning the graph if parse was successful
diff --git a/src/Text/RDF/RDF4H/NTriplesParser.hs b/src/Text/RDF/RDF4H/NTriplesParser.hs
--- a/src/Text/RDF/RDF4H/NTriplesParser.hs
+++ b/src/Text/RDF/RDF4H/NTriplesParser.hs
@@ -7,16 +7,14 @@
 
 where
 
--- TODO: switch to OverloadedStrings and use ByteString literals (?).
-
 import Data.RDF
 import Text.RDF.RDF4H.ParserUtils
 import Data.Char(isLetter, isDigit, isLower)
 import qualified Data.Map as Map
 import Text.Parsec
-import Text.Parsec.ByteString.Lazy
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
+import Text.Parsec.Text
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
 import Control.Monad (liftM,void)
 
 -- |NTriplesParser is an 'RdfParser' implementation for parsing RDF in the
@@ -37,10 +35,10 @@
 -- nt_ntripleDoc).
 
 -- |nt_ntripleDoc is simply zero or more lines.
-nt_ntripleDoc :: GenParser ByteString () [Maybe Triple]
+nt_ntripleDoc :: GenParser () [Maybe Triple]
 nt_ntripleDoc = manyTill nt_line eof
 
-nt_line :: GenParser ByteString () (Maybe Triple)
+nt_line :: GenParser () (Maybe Triple)
 nt_line       = 
     skipMany nt_space >>
      (nt_comment <|> nt_triple <|> nt_empty) >>=
@@ -52,13 +50,13 @@
 -- is already defined as the range #x0020-#x007E, so cr #x000D and
 -- lf #x000A are both already excluded. This returns Nothing as we are
 -- ignoring comments for now.
-nt_comment :: GenParser ByteString () (Maybe Triple)
+nt_comment :: GenParser () (Maybe Triple)
 nt_comment   = char '#' >> skipMany nt_character >> return Nothing
 
 -- A triple consists of whitespace-delimited subject, predicate, and object,
 -- followed by optional whitespace and a period, and possibly more
 -- whitespace.
-nt_triple :: GenParser ByteString () (Maybe Triple)
+nt_triple :: GenParser () (Maybe Triple)
 nt_triple    =
   do
     subj <- nt_subject
@@ -77,69 +75,69 @@
 -- quotes. A language literal may have '@' after the closing quote,
 -- followed by a language specifier. A datatype literal follows
 -- the closing quote with ^^ followed by the URI of the datatype.
-nt_literal :: GenParser ByteString () LValue
+nt_literal :: GenParser () LValue
 nt_literal = 
   do lit_str <- between_chars '"' '"' inner_literal 
      liftM (plainLL lit_str) (char '@' >> nt_language) <|>
-       liftM (typedL lit_str . mkFastString) (count 2 (char '^') >> nt_uriref) <|>
+       liftM (typedL lit_str) (count 2 (char '^') >> nt_uriref) <|>
        return (plainL lit_str)
-  where inner_literal = liftM B.concat (manyTill inner_string (lookAhead $ char '"'))
+  where inner_literal = liftM T.concat (manyTill inner_string (lookAhead $ char '"'))
 
 -- A language specifier of a language literal is any number of lowercase
 -- letters followed by any number of blocks consisting of a hyphen followed
 -- by one or more lowercase letters or digits.
-nt_language :: GenParser ByteString () ByteString
+nt_language :: GenParser () T.Text
 nt_language =
-  do str <- liftM B.pack (many (satisfy (\ c -> c == '-' || isLower c)))
-     if B.null str || B.last str == '-' || B.head str == '-'
-        then fail ("Invalid language string: '" ++ B.unpack str ++ "'")
+  do str <- liftM T.pack (many (satisfy (\ c -> c == '-' || isLower c)))
+     if T.null str || T.last str == '-' || T.head str == '-'
+        then fail ("Invalid language string: '" ++ T.unpack str ++ "'")
         else return str
 
 -- nt_empty is a line that isn't a comment or a triple. They appear in the
 -- parsed output as Nothing, whereas a real triple appears as (Just triple).
-nt_empty :: GenParser ByteString () (Maybe Triple)
+nt_empty :: GenParser () (Maybe Triple)
 nt_empty     = skipMany nt_space >> return Nothing
 
 -- A subject is either a URI reference for a resource or a node id for a
 -- blank node.
-nt_subject :: GenParser ByteString () Node
+nt_subject :: GenParser () Node
 nt_subject   =
   liftM unode nt_uriref <|>
   liftM bnode nt_nodeID
 
 -- A predicate may only be a URI reference to a resource.
-nt_predicate :: GenParser ByteString () Node
+nt_predicate :: GenParser () Node
 nt_predicate = liftM unode nt_uriref
 
 -- An object may be either a resource (represented by a URI reference),
 -- a blank node (represented by a node id), or an object literal.
-nt_object :: GenParser ByteString () Node
+nt_object :: GenParser () Node
 nt_object =
   liftM unode nt_uriref <|>
   liftM bnode nt_nodeID <|>
   liftM LNode nt_literal
 
 -- A URI reference is one or more nrab_character inside angle brackets.
-nt_uriref :: GenParser ByteString () ByteString
-nt_uriref = between_chars '<' '>' (liftM B.pack (many (satisfy ( /= '>'))))
+nt_uriref :: GenParser () T.Text
+nt_uriref = between_chars '<' '>' (liftM T.pack (many (satisfy ( /= '>'))))
 
 -- A node id is "_:" followed by a name.
-nt_nodeID :: GenParser ByteString () ByteString
+nt_nodeID :: GenParser () T.Text
 nt_nodeID = char '_' >> char ':' >> nt_name >>= \n -> 
-                return ('_' `B.cons'` (':' `B.cons'` n))
+                return ('_' `T.cons` (':' `T.cons` n))
 
 -- A name is a letter followed by any number of alpha-numeric characters.
-nt_name :: GenParser ByteString () ByteString
+nt_name :: GenParser () T.Text
 nt_name =
   do init <- letter
      rest <- many (satisfy isLetterOrDigit)
-     return $ B.pack (init:rest)
+     return $ T.pack (init:rest)
 
 isLetterOrDigit :: Char -> Bool
 isLetterOrDigit c = isLetter c || isDigit c
 
 -- An nt_character is any character except a double quote character.
-nt_character :: GenParser ByteString () Char
+nt_character :: GenParser () Char
 nt_character   =   satisfy is_nonquote_char
 
 -- A character is any Unicode value from ASCII space to decimal 126 (tilde).
@@ -152,24 +150,24 @@
 
 -- End-of-line consists of either lf or crlf.
 -- We also test for eof and consider that to match as well.
-nt_eoln :: GenParser ByteString () ()
+nt_eoln :: GenParser () ()
 nt_eoln =  eof <|> void (nt_cr >> nt_lf) <|> void nt_lf
 
 -- Whitespace is either a space or tab character. We must avoid using the
 -- built-in space combinator here, because it includes newline.
-nt_space :: GenParser ByteString () Char
+nt_space :: GenParser () Char
 nt_space = char ' ' <|> nt_tab
 
 -- Carriage return is \r.
-nt_cr :: GenParser ByteString () Char
+nt_cr :: GenParser () Char
 nt_cr          =   char '\r'
 
 -- Line feed is \n.
-nt_lf :: GenParser ByteString () Char
+nt_lf :: GenParser () Char
 nt_lf          =   char '\n'
 
 -- Tab is \t.
-nt_tab :: GenParser ByteString () Char
+nt_tab :: GenParser () Char
 nt_tab         =   char '\t'
 
 -- An inner_string is a fragment of a string (this is used inside double
@@ -178,7 +176,7 @@
 -- a newline (\n), a double-quote (\"), a 4-digit Unicode escape (\uxxxx
 -- where x is a hexadecimal digit), and an 8-digit Unicode escape
 -- (\Uxxxxxxxx where x is a hexadecimaldigit).
-inner_string :: GenParser ByteString () ByteString
+inner_string :: GenParser () T.Text
 inner_string =
   try (char '\\' >>
          ((char 't' >> return b_tab)  <|>
@@ -186,21 +184,21 @@
           (char 'n' >> return b_nl)  <|>
           (char '\\' >> return b_slash) <|>
           (char '"' >> return b_quote)   <|>
-          (char 'u' >> count 4 hexDigit >>= \cs -> return $ B.pack ('\\':'u':cs)) <|>
-          (char 'U' >> count 8 hexDigit >>= \cs -> return $ B.pack ('\\':'U':cs))))
-  <|> liftM B.pack
+          (char 'u' >> count 4 hexDigit >>= \cs -> return $ T.pack ('\\':'u':cs)) <|>
+          (char 'U' >> count 8 hexDigit >>= \cs -> return $ T.pack ('\\':'U':cs))))
+  <|> liftM T.pack
     (many (satisfy (\ c -> is_nonquote_char c && c /= '\\')))
 
-b_tab = B.singleton '\t'
-b_ret = B.singleton '\r'
-b_nl  = B.singleton '\n'
-b_slash = B.singleton '\\'
-b_quote = B.singleton '"'
+b_tab = T.singleton '\t'
+b_ret = T.singleton '\r'
+b_nl  = T.singleton '\n'
+b_slash = T.singleton '\\'
+b_quote = T.singleton '"'
 
-between_chars :: Char -> Char -> GenParser ByteString () ByteString -> GenParser ByteString () ByteString
+between_chars :: Char -> Char -> GenParser () T.Text -> GenParser () T.Text
 between_chars start end parser = char start >> parser >>= \res -> char end >> return res
 
-parseString' :: forall rdf. (RDF rdf) => ByteString -> Either ParseFailure rdf
+parseString' :: forall rdf. (RDF rdf) => T.Text -> Either ParseFailure rdf
 parseString' bs = handleParse mkRdf (runParser nt_ntripleDoc () "" bs)
 
 parseURL' :: forall rdf. (RDF rdf) => String -> IO (Either ParseFailure rdf)
@@ -208,13 +206,13 @@
 
 parseFile' :: forall rdf. (RDF rdf) => String -> IO (Either ParseFailure rdf)
 parseFile' path = liftM (handleParse mkRdf . runParser nt_ntripleDoc () path)
-                   (B.readFile path)
+                   (TIO.readFile path)
 
 handleParse :: forall rdf. (RDF rdf) => (Triples -> Maybe BaseUrl -> PrefixMappings -> rdf) ->
                                         Either ParseError [Maybe Triple] ->
                                         Either ParseFailure rdf
 handleParse _mkRdf result
---  | B.length rem /= 0 = (Left $ ParseFailure $ "Invalid Document. Unparseable end of document: " ++ B.unpack rem)
+--  | T.length rem /= 0 = (Left $ ParseFailure $ "Invalid Document. Unparseable end of document: " ++ T.unpack rem)
   | otherwise          = 
       case result of
         Left err -> Left  $ ParseFailure $ "Parse failure: \n" ++ show err
@@ -224,9 +222,9 @@
     conv (Nothing:ts)  = conv ts
     conv (Just t:ts) = t : conv ts
 
-_test :: GenParser ByteString () a -> String -> IO a
+_test :: GenParser () a -> String -> IO a
 _test p str =
     case result of
       (Left err) -> putStr "ParseError: '" >> putStr (show err) >> putStr "\n" >> error ""
       (Right a)  -> return a
-  where result = runParser p () "" (B.pack str)
+  where result = runParser p () "" (T.pack str)
diff --git a/src/Text/RDF/RDF4H/NTriplesSerializer.hs b/src/Text/RDF/RDF4H/NTriplesSerializer.hs
--- a/src/Text/RDF/RDF4H/NTriplesSerializer.hs
+++ b/src/Text/RDF/RDF4H/NTriplesSerializer.hs
@@ -7,9 +7,9 @@
 
 import Data.RDF
 import Data.RDF.Utils
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
-import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import Data.Text.Encoding
+import qualified Data.ByteString as B
 import Control.Monad (void)
 import System.IO
 
@@ -43,10 +43,10 @@
 _writeNode :: Handle -> Node -> IO ()
 _writeNode h node =
   case node of
-    (UNode fs)  -> hPutChar h '<' >>
-                     hPutStrRev h (value fs) >>
+    (UNode bs)  -> hPutChar h '<' >>
+                     hPutStrRev h bs >>
                      hPutChar h '>'
-    (BNode gId) -> hPutStrRev h (value gId)
+    (BNode gId) -> hPutStrRev h gId
     (BNodeGen i)-> putStr "_:genid" >> hPutStr h (show i)
     (LNode n)   -> _writeLValue h n
 
@@ -56,17 +56,17 @@
     (PlainL lit)       -> _writeLiteralString h lit
     (PlainLL lit lang) -> _writeLiteralString h lit >>
                             hPutStr h "@" >>
-                            BL.hPutStr h lang
+                            B.hPutStr h (encodeUtf8 lang)
     (TypedL lit dtype) -> _writeLiteralString h lit >>
                             hPutStr h "^^<" >>
-                            hPutStrRev h (value dtype) >>
+                            hPutStrRev h dtype >>
                             hPutStr h ">"
 
 -- TODO: this is REALLY slow.
-_writeLiteralString:: Handle -> ByteString -> IO ()
+_writeLiteralString:: Handle -> T.Text -> IO ()
 _writeLiteralString h bs =
   do hPutChar h '"'
-     B.foldl' writeChar (return ()) bs
+     T.foldl' writeChar (return ()) bs
      hPutChar h '"'
   where
     -- the seq is necessary in writeChar to ensure all chars
@@ -81,9 +81,9 @@
         '\\' ->  void (hPutChar h '\\' >> hPutChar h '\\')
         _    ->  void (hPutChar h c)
 
-_bs1, _bs2 :: ByteString
-_bs1 = B.pack "\nthis \ris a \\U00015678long\t\nliteral\\uABCD\n"
-_bs2 = B.pack "\nan \\U00015678 escape\n"
+_bs1, _bs2 :: T.Text
+_bs1 = T.pack "\nthis \ris a \\U00015678long\t\nliteral\\uABCD\n"
+_bs2 = T.pack "\nan \\U00015678 escape\n"
 
 _w :: IO ()
 _w = _writeLiteralString stdout _bs1
diff --git a/src/Text/RDF/RDF4H/ParserUtils.hs b/src/Text/RDF/RDF4H/ParserUtils.hs
--- a/src/Text/RDF/RDF4H/ParserUtils.hs
+++ b/src/Text/RDF/RDF4H/ParserUtils.hs
@@ -7,8 +7,11 @@
 import Network.URI
 import Network.HTTP
 import Data.Char(intToDigit)
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
+-- import Data.ByteString.Lazy.Char8(ByteString)
+-- import qualified Data.ByteString as B
+import Data.Text.Encoding (decodeUtf8)
+import qualified Data.ByteString.Char8 as B
+import qualified Data.Text as T
 import Data.Maybe (fromMaybe)
 
 -- A convenience function for terminating a parse with a parse failure, using
@@ -22,7 +25,7 @@
 justTriples = map (fromMaybe (error "ParserUtils.justTriples")) .
               filter (/= Nothing)
 
-_parseURL :: RDF rdf => (ByteString -> Either ParseFailure rdf)  -> String -> IO (Either ParseFailure rdf)
+_parseURL :: RDF rdf => (T.Text -> Either ParseFailure rdf)  -> String -> IO (Either ParseFailure rdf)
 _parseURL parseFunc url =
   maybe
     (return (Left (ParseFailure $ "Unable to parse URL: " ++ url)))
@@ -36,10 +39,10 @@
         case resp of
           (Left e)    -> return (errResult $ "couldn't retrieve from URL: " ++ show url ++ " [" ++ show e ++ "]")
           (Right res) -> case rspCode res of
-                           (2, 0, 0) -> return $ parseFunc (rspBody res)
+                           (2, 0, 0) -> return $ parseFunc (decodeUtf8 (rspBody res))
                            _         -> return (errResult $ "couldn't retrieve from URL: " ++ httpError res)
 
-request :: URI -> HTTPRequest ByteString
+request :: URI -> HTTPRequest B.ByteString
 request uri = Request { rqURI = uri,
                         rqMethod = GET,
                         rqHeaders = [Header HdrConnection "close"],
diff --git a/src/Text/RDF/RDF4H/TurtleParser.hs b/src/Text/RDF/RDF4H/TurtleParser.hs
--- a/src/Text/RDF/RDF4H/TurtleParser.hs
+++ b/src/Text/RDF/RDF4H/TurtleParser.hs
@@ -11,11 +11,10 @@
 import Data.RDF.Namespace
 import Text.RDF.RDF4H.ParserUtils
 import Text.Parsec
-import Text.Parsec.ByteString.Lazy
+import Text.Parsec.Text
 import qualified Data.Map as Map
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
-import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
 import Data.Sequence(Seq, (|>))
 import qualified Data.Sequence as Seq
 import qualified Data.Foldable as F
@@ -35,7 +34,7 @@
 -- To use this parser, pass a 'TurtleParser' value as the first argument to any of
 -- the 'parseString', 'parseFile', or 'parseURL' methods of the 'RdfParser' type
 -- class.
-data TurtleParser = TurtleParser (Maybe BaseUrl) (Maybe ByteString)
+data TurtleParser = TurtleParser (Maybe BaseUrl) (Maybe T.Text)
 
 -- |'TurtleParser' is an instance of 'RdfParser'.
 instance RdfParser TurtleParser where
@@ -45,7 +44,7 @@
 
 type ParseState =
   (Maybe BaseUrl,    -- the current BaseUrl, may be Nothing initially, but not after it is once set
-   Maybe ByteString, -- the docUrl, which never changes and is used to resolve <> in the document.
+   Maybe T.Text, -- the docUrl, which never changes and is used to resolve <> in the document.
    Int,              -- the id counter, containing the value of the next id to be used
    PrefixMappings,   -- the mappings from prefix to URI that are encountered while parsing
    [Subject],        -- stack of current subject nodes, if we have parsed a subject but not finished the triple
@@ -53,11 +52,11 @@
    [Bool],           -- a stack of values to indicate that we're processing a (possibly nested) collection; top True indicates just started (on first element)
    Seq Triple)       -- the triples encountered while parsing; always added to on the right side
 
-t_turtleDoc :: GenParser ByteString ParseState (Seq Triple, PrefixMappings)
+t_turtleDoc :: GenParser ParseState (Seq Triple, PrefixMappings)
 t_turtleDoc =
   many t_statement >> (eof <?> "eof") >> getState >>= \(_, _, _, pms, _, _, _, ts) -> return (ts, pms)
 
-t_statement :: GenParser ByteString ParseState ()
+t_statement :: GenParser ParseState ()
 t_statement = d <|> t <|> void (many1 t_ws <?> "blankline-whitespace")
   where
     d = void
@@ -69,26 +68,26 @@
       (char '.' <?> "end-of-triple-period") >>
       (many t_ws <?> "triple-whitespace2"))
 
-t_triples :: GenParser ByteString ParseState ()
+t_triples :: GenParser ParseState ()
 t_triples = t_subject >> (many1 t_ws <?> "subject-predicate-whitespace") >> t_predicateObjectList >> resetSubjectPredicate
 
-t_directive :: GenParser ByteString ParseState ()
+t_directive :: GenParser ParseState ()
 t_directive = t_prefixID <|> t_base
 
-t_resource :: GenParser ByteString ParseState ByteString
+t_resource :: GenParser ParseState T.Text
 t_resource =  try t_uriref <|> t_qname
 
-t_prefixID :: GenParser ByteString ParseState ()
+t_prefixID :: GenParser ParseState ()
 t_prefixID =
   do try (string "@prefix" <?> "@prefix-directive")
-     pre <- (many1 t_ws <?> "whitespace-after-@prefix") >> option B.empty t_prefixName
+     pre <- (many1 t_ws <?> "whitespace-after-@prefix") >> option T.empty t_prefixName
      char ':' >> (many1 t_ws <?> "whitespace-after-@prefix-colon")
      uriFrag <- t_uriref
      (bUrl, dUrl, _, PrefixMappings pms, _, _, _, _) <- getState
      updatePMs $ Just (PrefixMappings $ Map.insert pre (absolutizeUrl bUrl dUrl uriFrag) pms)
      return ()
 
-t_base :: GenParser ByteString ParseState ()
+t_base :: GenParser ParseState ()
 t_base =
   do try (string "@base" <?> "@base-directive")
      many1 t_ws <?> "whitespace-after-@base"
@@ -97,32 +96,32 @@
      dUrl <- currDocUrl
      updateBaseUrl (Just $ Just $ newBaseUrl bUrl (absolutizeUrl bUrl dUrl urlFrag))
 
-t_verb :: GenParser ByteString ParseState ()
+t_verb :: GenParser ParseState ()
 t_verb = (try t_predicate <|> (char 'a' >> return rdfTypeNode)) >>= pushPred
 
-t_predicate :: GenParser ByteString ParseState Node
-t_predicate = liftM (UNode . mkFastString) (t_resource <?> "resource")
+t_predicate :: GenParser ParseState Node
+t_predicate = liftM UNode (t_resource <?> "resource")
 
-t_nodeID  :: GenParser ByteString ParseState ByteString
-t_nodeID = do { try (string "_:"); cs <- t_name; return $! s2b "_:" `B.append` cs }
+t_nodeID  :: GenParser ParseState T.Text
+t_nodeID = do { try (string "_:"); cs <- t_name; return $! "_:" `T.append` cs }
 
-t_qname :: GenParser ByteString ParseState ByteString
+t_qname :: GenParser ParseState T.Text
 t_qname =
-  do pre <- option B.empty (try t_prefixName)
+  do pre <- option T.empty (try t_prefixName)
      char ':'
-     name <- option B.empty t_name
+     name <- option T.empty t_name
      (bUrl, _, _, pms, _, _, _, _) <- getState
-     return $ resolveQName bUrl pre pms `B.append` name
+     return $ resolveQName bUrl pre pms `T.append` name
 
-t_subject :: GenParser ByteString ParseState ()
+t_subject :: GenParser ParseState ()
 t_subject =
   simpleBNode <|>
   resource <|>
   nodeId <|>
   between (char '[') (char ']') poList
   where
-    resource    = liftM (UNode . mkFastString) (t_resource <?> "subject resource") >>= pushSubj
-    nodeId      = liftM (BNode . mkFastString) (t_nodeID <?> "subject nodeID") >>= pushSubj
+    resource    = liftM UNode (t_resource <?> "subject resource") >>= pushSubj
+    nodeId      = liftM BNode (t_nodeID <?> "subject nodeID") >>= pushSubj
     simpleBNode = try (string "[]") >> nextIdCounter >>=  pushSubj . BNodeGen
     poList      = void
                 (nextIdCounter >>= pushSubj . BNodeGen >> many t_ws >>
@@ -130,7 +129,7 @@
                 many t_ws)
 
 -- verb ws+ objectList ( ws* ';' ws* verb ws+ objectList )* (ws* ';')?
-t_predicateObjectList :: GenParser ByteString ParseState ()
+t_predicateObjectList :: GenParser ParseState ()
 t_predicateObjectList =
   do t_verb <?> "verb"     -- pushes pred onto pred stack
      many1 t_ws   <?> "polist-whitespace-after-verb"
@@ -139,18 +138,18 @@
      popPred               -- pop off the predicate pushed by 1st t_verb
      return ()
 
-t_objectList :: GenParser ByteString ParseState ()
+t_objectList :: GenParser ParseState ()
 t_objectList = -- t_object actually adds the triples
   void
   ((t_object <?> "object") >>
   many (try (many t_ws >> char ',' >> many t_ws >> t_object)))
 
-t_object :: GenParser ByteString ParseState ()
+t_object :: GenParser ParseState ()
 t_object =
   do inColl      <- isInColl          -- whether this object is in a collection
      onFirstItem <- onCollFirstItem   -- whether we're on the first item of the collection
      let processObject = (t_literal >>= addTripleForObject) <|>
-                          (liftM (UNode . mkFastString) t_resource >>= addTripleForObject) <|>
+                          (liftM UNode t_resource >>= addTripleForObject) <|>
                           blank_as_obj <|> t_collection
      case (inColl, onFirstItem) of
        (False, _)    -> processObject
@@ -162,7 +161,7 @@
 
 -- collection: '(' ws* itemList? ws* ')'
 -- itemList:      object (ws+ object)*
-t_collection:: GenParser ByteString ParseState ()
+t_collection:: GenParser ParseState ()
 t_collection = 
   -- ( object1 object2 ) is short for:
   -- [ rdf:first object1; rdf:rest [ rdf:first object2; rdf:rest rdf:nil ] ]
@@ -180,10 +179,10 @@
        finishColl
        return ()
 
-blank_as_obj :: GenParser ByteString ParseState ()
+blank_as_obj :: GenParser ParseState ()
 blank_as_obj =
   -- if a node id, like _:a1, then create a BNode and add the triple
-  (liftM (BNode . mkFastString) t_nodeID >>= addTripleForObject) <|>
+  (liftM BNode t_nodeID >>= addTripleForObject) <|>
   -- if a simple blank like [], do likewise
   (genBlank >>= addTripleForObject) <|>
   -- if a blank containing a predicateObjectList, like [ :b :c; :b :d ]
@@ -199,18 +198,18 @@
 
 
 rdfTypeNode, rdfNilNode, rdfFirstNode, rdfRestNode :: Node
-rdfTypeNode   = UNode $ mkFastString $ mkUri rdf $ s2b "type"
-rdfNilNode    = UNode $ mkFastString $ mkUri rdf $ s2b "nil"
-rdfFirstNode  = UNode $ mkFastString $ mkUri rdf $ s2b "first"
-rdfRestNode   = UNode $ mkFastString $ mkUri rdf $ s2b "rest"
+rdfTypeNode   = UNode $ mkUri rdf "type"
+rdfNilNode    = UNode $ mkUri rdf "nil"
+rdfFirstNode  = UNode $ mkUri rdf "first"
+rdfRestNode   = UNode $ mkUri rdf "rest"
 
-xsdIntUri, xsdDoubleUri, xsdDecimalUri, xsdBooleanUri :: FastString
-xsdIntUri     =  mkFastString $! mkUri xsd $! s2b "integer"
-xsdDoubleUri  =  mkFastString $! mkUri xsd $! s2b "double"
-xsdDecimalUri =  mkFastString $! mkUri xsd $! s2b "decimal"
-xsdBooleanUri =  mkFastString $! mkUri xsd $! s2b "boolean"
+xsdIntUri, xsdDoubleUri, xsdDecimalUri, xsdBooleanUri :: T.Text
+xsdIntUri     =   mkUri xsd "integer"
+xsdDoubleUri  =   mkUri xsd "double"
+xsdDecimalUri =  mkUri xsd "decimal"
+xsdBooleanUri =  mkUri xsd "boolean"
 
-t_literal :: GenParser ByteString ParseState Node
+t_literal :: GenParser ParseState Node
 t_literal =
   try str_literal <|>
   liftM (`mkLNode` xsdIntUri) (try t_integer)   <|>
@@ -218,123 +217,123 @@
   liftM (`mkLNode` xsdDecimalUri) (try t_decimal) <|>
   liftM (`mkLNode` xsdBooleanUri) t_boolean
   where
-    mkLNode :: ByteString -> FastString -> Node
-    mkLNode bs fs = LNode (typedL bs fs)
+    mkLNode :: T.Text -> T.Text -> Node
+    mkLNode bsType bs = LNode (typedL bsType bs)
 
-str_literal :: GenParser ByteString ParseState Node
+str_literal :: GenParser ParseState Node
 str_literal =
   do str <- t_quotedString <?> "quotedString"
-     liftM (LNode . typedL str . mkFastString)
+     liftM (LNode . typedL str)
       (try (count 2 (char '^')) >> t_resource) <|>
       liftM (lnode . plainLL str) (char '@' >> t_language) <|>
       return (lnode $ plainL str)
 
-t_quotedString  :: GenParser ByteString ParseState ByteString
+t_quotedString  :: GenParser ParseState T.Text
 t_quotedString = t_longString <|> t_string
 
 -- a non-long string: any number of scharacters (echaracter without ") inside doublequotes.
-t_string  :: GenParser ByteString ParseState ByteString
-t_string = liftM B.concat (between (char '"') (char '"') (many t_scharacter))
+t_string  :: GenParser ParseState T.Text
+t_string = liftM T.concat (between (char '"') (char '"') (many t_scharacter))
 
-t_longString  :: GenParser ByteString ParseState ByteString
+t_longString  :: GenParser ParseState T.Text
 t_longString =
   do
     try tripleQuote
-    strVal <- liftM B.concat (many longString_char)
+    strVal <- liftM T.concat (many longString_char)
     tripleQuote
     return strVal
   where
     tripleQuote = count 3 (char '"')
 
-t_integer :: GenParser ByteString ParseState ByteString
+t_integer :: GenParser ParseState T.Text
 t_integer =
   do sign <- sign_parser <?> "+-"
      ds <- many1 digit   <?> "digit"
      notFollowedBy (char '.')
      -- integer must be in canonical format, with no leading plus sign or leading zero
-     return $! (s2b sign `B.append` s2b ds)
+     return $! ( s2t sign `T.append` s2t ds)
 
-t_double :: GenParser ByteString ParseState ByteString
+t_double :: GenParser ParseState T.Text
 t_double =
   do sign <- sign_parser <?> "+-"
-     rest <- try (do { ds <- many1 digit <?> "digit";  char '.'; ds' <- many digit <?> "digit"; e <- t_exponent <?> "exponent"; return (s2b ds `B.snoc` '.' `B.append` s2b ds' `B.append` e) }) <|>
-             try (do { char '.'; ds <- many1 digit <?> "digit"; e <- t_exponent <?> "exponent"; return ('.' `B.cons` s2b ds `B.append` e) }) <|>
-             try (do { ds <- many1 digit <?> "digit"; e <- t_exponent <?> "exponent"; return (s2b ds `B.append` e) })
-     return $! s2b sign `B.append` rest
+     rest <- try (do { ds <- many1 digit <?> "digit";  char '.'; ds' <- many digit <?> "digit"; e <- t_exponent <?> "exponent"; return ( s2t ds `T.snoc` '.' `T.append`  s2t ds' `T.append` e) }) <|>
+             try (do { char '.'; ds <- many1 digit <?> "digit"; e <- t_exponent <?> "exponent"; return ('.' `T.cons`  s2t ds `T.append` e) }) <|>
+             try (do { ds <- many1 digit <?> "digit"; e <- t_exponent <?> "exponent"; return ( s2t ds `T.append` e) })
+     return $! s2t sign `T.append` rest
 
-sign_parser :: GenParser ByteString ParseState String
+sign_parser :: GenParser ParseState String
 sign_parser = option "" (oneOf "-+" >>= (\c -> return [c]))
 
-t_decimal :: GenParser ByteString ParseState ByteString
+t_decimal :: GenParser ParseState T.Text
 t_decimal =
   do sign <- sign_parser
      rest <- try (do ds <- many digit <?> "digit"; char '.'; ds' <- option "" (many digit); return (ds ++ ('.':ds')))
              <|> try (do { char '.'; ds <- many1 digit <?> "digit"; return ('.':ds) })
              <|> many1 digit <?> "digit"
-     return $ s2b sign `B.append` s2b rest
+     return $ s2t sign `T.append`  s2t rest
 
-t_exponent :: GenParser ByteString ParseState ByteString
+t_exponent :: GenParser ParseState T.Text
 t_exponent = do e <- oneOf "eE"
                 s <- option "" (oneOf "-+" >>= \c -> return [c])
                 ds <- many1 digit;
-                return $! (e `B.cons` (s2b s `B.append` s2b ds))
+                return $! (e `T.cons` ( s2t s `T.append` s2t ds))
 
-t_boolean :: GenParser ByteString ParseState ByteString
+t_boolean :: GenParser ParseState T.Text
 t_boolean =
-  try (liftM s2b (string "true") <|>
-  liftM s2b (string "true"))
+  try (liftM s2t (string "true") <|>
+  liftM s2t (string "false"))
 
-t_comment :: GenParser ByteString ParseState ()
+t_comment :: GenParser ParseState ()
 t_comment =
   void (char '#' >> many (satisfy (\ c -> c /= '\n' && c /= '\r')))
 
-t_ws  :: GenParser ByteString ParseState ()
+t_ws  :: GenParser ParseState ()
 t_ws =
     (void (try (char '\t' <|> char '\n' <|> char '\r' <|> char ' '))
     <|> try t_comment)
    <?> "whitespace-or-comment"
 
 
-t_language  :: GenParser ByteString ParseState ByteString
+t_language  :: GenParser ParseState T.Text
 t_language =
   do init <- many1 lower;
-     rest <- many (do {char '-'; cs <- many1 (lower <|> digit); return (s2b ('-':cs))})
-     return $! (s2b init `B.append` B.concat rest)
+     rest <- many (do {char '-'; cs <- many1 (lower <|> digit); return ( s2t ('-':cs))})
+     return $! ( s2t init `T.append` T.concat rest)
 
-identifier :: GenParser ByteString ParseState Char -> GenParser ByteString ParseState Char -> GenParser ByteString ParseState ByteString
-identifier initial rest = initial >>= \i -> many rest >>= \r -> return (s2b (i:r))
+identifier :: GenParser ParseState Char -> GenParser ParseState Char -> GenParser ParseState T.Text
+identifier initial rest = initial >>= \i -> many rest >>= \r -> return ( s2t (i:r))
 
-t_prefixName :: GenParser ByteString ParseState ByteString
+t_prefixName :: GenParser ParseState T.Text
 t_prefixName = identifier t_nameStartCharMinusUnderscore t_nameChar
 
-t_name :: GenParser ByteString ParseState ByteString
+t_name :: GenParser ParseState T.Text
 t_name = identifier t_nameStartChar t_nameChar
 
-t_uriref :: GenParser ByteString ParseState ByteString
+t_uriref :: GenParser ParseState T.Text
 t_uriref = between (char '<') (char '>') t_relativeURI
 
-t_relativeURI  :: GenParser ByteString ParseState ByteString
+t_relativeURI  :: GenParser ParseState T.Text
 t_relativeURI =
-  do frag <- liftM (B.pack . concat) (many t_ucharacter)
+  do frag <- liftM (s2t . concat) (many t_ucharacter)
      bUrl <- currBaseUrl
      dUrl <- currDocUrl
      return $ absolutizeUrl bUrl dUrl frag
 
--- We make this String rather than ByteString because we want
+-- We make this String rather than T.Text because we want
 -- t_relativeURI (the only place it's used) to have chars so that
--- when it creates a ByteString it can all be in one chunk.
-t_ucharacter  :: GenParser ByteString ParseState String
+-- when it creates a T.Text it can all be in one chunk.
+t_ucharacter  :: GenParser ParseState String
 t_ucharacter =
-  try (liftM B.unpack unicode_escape) <|>
+  try (liftM t2s unicode_escape) <|>
   try (string "\\>") <|>
-  liftM B.unpack (non_ctrl_char_except ">")
+  liftM t2s (non_ctrl_char_except ">")
 
-t_nameChar :: GenParser ByteString ParseState Char
+t_nameChar :: GenParser ParseState Char
 t_nameChar = t_nameStartChar <|> char '-' <|> char '\x00B7' <|> satisfy f
   where
     f = flip in_range [('0', '9'), ('\x0300', '\x036F'), ('\x203F', '\x2040')]
 
-longString_char  :: GenParser ByteString ParseState ByteString
+longString_char  :: GenParser ParseState T.Text
 longString_char  =
   specialChar        <|> -- \r|\n|\t as single char
   try escapedChar    <|> -- an backslash-escaped tab, newline, linefeed, backslash or doublequote
@@ -352,16 +351,16 @@
     oneDoubleQuote  = char '"' >> notFollowedBy (char '"') >> bs1 '"'
     safeNonCtrlChar = non_ctrl_char_except "\\\""
 
-bs1 :: Char -> GenParser ByteString ParseState ByteString
-bs1 = return . B.singleton
+bs1 :: Char -> GenParser ParseState T.Text
+bs1 = return . T.singleton
 
-bs :: String -> GenParser ByteString ParseState ByteString
-bs = return . B.pack
+bs :: String -> GenParser ParseState T.Text
+bs = return . s2t
 
-t_nameStartChar  :: GenParser ByteString ParseState Char
+t_nameStartChar  :: GenParser ParseState Char
 t_nameStartChar = char '_' <|> t_nameStartCharMinusUnderscore
 
-t_nameStartCharMinusUnderscore  :: GenParser ByteString ParseState Char
+t_nameStartCharMinusUnderscore  :: GenParser ParseState Char
 t_nameStartCharMinusUnderscore = try $ satisfy $ flip in_range blocks
   where
     blocks = [('A', 'Z'), ('a', 'z'), ('\x00C0', '\x00D6'),
@@ -372,31 +371,31 @@
               ('\xF900', '\xFDCF'), ('\xFDF0', '\xFFFD'),
               ('\x10000', '\xEFFFF')]
 
-t_hex  :: GenParser ByteString ParseState Char
+t_hex  :: GenParser ParseState Char
 t_hex = satisfy (\c -> isDigit c || (c >= 'A' && c <= 'F')) <?> "hexadecimal digit"
 
 -- characters used in (non-long) strings; any echaracters except ", or an escaped \"
 -- echaracter - #x22 ) | '\"'
-t_scharacter  :: GenParser ByteString ParseState ByteString
+t_scharacter  :: GenParser ParseState T.Text
 t_scharacter =
-  (try (string "\\\"") >> return (B.singleton '"'))
+  (try (string "\\\"") >> return (T.singleton '"'))
      <|> try (do {char '\\';
-                  (char 't' >> return (B.singleton '\t')) <|>
-                  (char 'n' >> return (B.singleton '\n')) <|>
-                  (char 'r' >> return (B.singleton '\r'))}) -- echaracter part 1
+                  (char 't' >> return (T.singleton '\t')) <|>
+                  (char 'n' >> return (T.singleton '\n')) <|>
+                  (char 'r' >> return (T.singleton '\r'))}) -- echaracter part 1
      <|> unicode_escape
      <|> (non_ctrl_char_except "\\\"" >>= \s -> return $! s) -- echaracter part 2 minus "
 
-unicode_escape  :: GenParser ByteString ParseState ByteString
+unicode_escape  :: GenParser ParseState T.Text
 unicode_escape =
- (char '\\' >> return (B.singleton '\\')) >>
- ((char '\\' >> return (s2b "\\\\")) <|>
-  (char 'u' >> count 4 t_hex >>= \cs -> return $! s2b "\\u" `B.append` s2b cs) <|>
-  (char 'U' >> count 8 t_hex >>= \cs -> return $! s2b "\\U" `B.append` s2b cs))
+ (char '\\' >> return (T.singleton '\\')) >>
+ ((char '\\' >> return "\\\\") <|>
+  (char 'u' >> count 4 t_hex >>= \cs -> return $!  "\\u" `T.append`  s2t cs) <|>
+  (char 'U' >> count 8 t_hex >>= \cs -> return $!  "\\U" `T.append` s2t cs))
 
-non_ctrl_char_except  :: String -> GenParser ByteString ParseState ByteString
+non_ctrl_char_except  :: String -> GenParser ParseState T.Text
 non_ctrl_char_except cs =
-  liftM B.singleton
+  liftM T.singleton
     (satisfy (\ c -> c <= '\1114111' && (c >= ' ' && c `notElem` cs)))
 
 {-# INLINE in_range #-}
@@ -406,96 +405,96 @@
 -- Resolve a prefix using the given prefix mappings and base URL. If the prefix is
 -- empty, then the base URL will be used if there is a base URL and if the map
 -- does not contain an entry for the empty prefix.
-resolveQName :: Maybe BaseUrl -> ByteString -> PrefixMappings -> ByteString
+resolveQName :: Maybe BaseUrl -> T.Text -> PrefixMappings -> T.Text
 resolveQName mbaseUrl prefix (PrefixMappings pms') =
-  case (mbaseUrl, B.null prefix) of
-    (Just (BaseUrl base), True)  ->  Map.findWithDefault base BL.empty pms'
+  case (mbaseUrl, T.null prefix) of
+    (Just (BaseUrl base), True)  ->  Map.findWithDefault base T.empty pms'
     (Nothing,             True)  ->  err1
     (_,                   _   )  ->  Map.findWithDefault err2 prefix pms'
   where
     err1 = error  "Cannot resolve empty QName prefix to a Base URL."
-    err2 = error ("Cannot resolve QName prefix: " ++ B.unpack prefix)
+    err2 = error ("Cannot resolve QName prefix: " ++ t2s prefix)
 
 -- Resolve a URL fragment found on the right side of a prefix mapping by converting it to an absolute URL if possible.
-absolutizeUrl :: Maybe BaseUrl -> Maybe ByteString -> ByteString -> ByteString
+absolutizeUrl :: Maybe BaseUrl -> Maybe T.Text -> T.Text -> T.Text
 absolutizeUrl mbUrl mdUrl urlFrag =
   if isAbsoluteUri urlFrag then urlFrag else
     (case (mbUrl, mdUrl) of
          (Nothing, Nothing) -> urlFrag
-         (Just (BaseUrl bUrl), Nothing) -> bUrl `B.append` urlFrag
+         (Just (BaseUrl bUrl), Nothing) -> bUrl `T.append` urlFrag
          (Nothing, Just dUrl) -> if isHash urlFrag then
-                                     dUrl `B.append` urlFrag else urlFrag
+                                     dUrl `T.append` urlFrag else urlFrag
          (Just (BaseUrl bUrl), Just dUrl) -> (if isHash urlFrag then dUrl
                                                   else bUrl)
-                                                 `B.append` urlFrag)
+                                                 `T.append` urlFrag)
   where
-    isHash bs = B.length bs == 1 && B.head bs == '#'
+    isHash bs = T.length bs == 1 && T.head bs == '#'
 
 {-# INLINE isAbsoluteUri #-}
-isAbsoluteUri :: ByteString -> Bool
-isAbsoluteUri = B.elem ':'
+isAbsoluteUri :: T.Text -> Bool
+isAbsoluteUri = T.isInfixOf (s2t [':'])
 
-newBaseUrl :: Maybe BaseUrl -> ByteString -> BaseUrl
+newBaseUrl :: Maybe BaseUrl -> T.Text -> BaseUrl
 newBaseUrl Nothing                url = BaseUrl url
 newBaseUrl (Just (BaseUrl bUrl)) url = BaseUrl $! mkAbsoluteUrl bUrl url
 
 {-# INLINE mkAbsoluteUrl #-}
 -- Make an absolute URL by returning as is if already an absolute URL and otherwise
 -- appending the URL to the given base URL.
-mkAbsoluteUrl :: ByteString -> ByteString -> ByteString
+mkAbsoluteUrl :: T.Text -> T.Text -> T.Text
 mkAbsoluteUrl base url =
-  if isAbsoluteUri url then url else base `B.append` url
+  if isAbsoluteUri url then url else base `T.append` url
 
-currBaseUrl :: GenParser ByteString ParseState (Maybe BaseUrl)
+currBaseUrl :: GenParser ParseState (Maybe BaseUrl)
 currBaseUrl = getState >>= \(bUrl, _, _, _, _, _, _, _) -> return bUrl
 
-currDocUrl :: GenParser ByteString ParseState (Maybe ByteString)
+currDocUrl :: GenParser ParseState (Maybe T.Text)
 currDocUrl = getState >>= \(_, dUrl, _, _, _, _, _, _) -> return dUrl
 
-pushSubj :: Subject -> GenParser ByteString ParseState ()
+pushSubj :: Subject -> GenParser ParseState ()
 pushSubj s = getState >>= \(bUrl, dUrl, i, pms, ss, ps, cs, ts) ->
                   setState (bUrl, dUrl, i, pms, s:ss, ps, cs, ts)
 
-popSubj :: GenParser ByteString ParseState Subject
+popSubj :: GenParser ParseState Subject
 popSubj = getState >>= \(bUrl, dUrl, i, pms, ss, ps, cs, ts) ->
                 setState (bUrl, dUrl, i, pms, tail ss, ps, cs, ts) >>
                   when (null ss) (error "Cannot pop subject off empty stack.") >>
                   return (head ss)
 
-pushPred :: Predicate -> GenParser ByteString ParseState ()
+pushPred :: Predicate -> GenParser ParseState ()
 pushPred p = getState >>= \(bUrl, dUrl, i, pms, ss, ps, cs, ts) ->
                   setState (bUrl, dUrl, i, pms, ss, p:ps, cs, ts)
 
-popPred :: GenParser ByteString ParseState Predicate
+popPred :: GenParser ParseState Predicate
 popPred = getState >>= \(bUrl, dUrl, i, pms, ss, ps, cs, ts) ->
                 setState (bUrl, dUrl, i, pms, ss, tail ps, cs, ts) >>
                   when (null ps) (error "Cannot pop predicate off empty stack.") >>
                   -- _trace (show ps) (return ()) >>
                   return (head ps)
 
-isInColl :: GenParser ByteString ParseState Bool
+isInColl :: GenParser ParseState Bool
 isInColl = getState >>= \(_, _, _, _, _, _, cs, _) -> return . not . null $ cs
 
-updateBaseUrl :: Maybe (Maybe BaseUrl) -> GenParser ByteString ParseState ()
+updateBaseUrl :: Maybe (Maybe BaseUrl) -> GenParser ParseState ()
 updateBaseUrl val = _modifyState val no no no no no
 
 -- combines get_current and increment into a single function
-nextIdCounter :: GenParser ByteString ParseState Int
+nextIdCounter :: GenParser ParseState Int
 nextIdCounter = getState >>= \(bUrl, dUrl, i, pms, s, p, cs, ts) ->
                 setState (bUrl, dUrl, i+1, pms, s, p, cs, ts) >> return i
 
-updatePMs :: Maybe PrefixMappings -> GenParser ByteString ParseState ()
+updatePMs :: Maybe PrefixMappings -> GenParser ParseState ()
 updatePMs val = _modifyState no no val no no no
 
 -- Register that we have begun processing a collection
-beginColl :: GenParser ByteString ParseState ()
+beginColl :: GenParser ParseState ()
 beginColl = getState >>= \(bUrl, dUrl, i, pms, s, p, cs, ts) ->
             setState (bUrl, dUrl, i, pms, s, p, True:cs, ts)
 
-onCollFirstItem :: GenParser ByteString ParseState Bool
+onCollFirstItem :: GenParser ParseState Bool
 onCollFirstItem = getState >>= \(_, _, _, _, _, _, cs, _) -> return (not (null cs) && head cs)
 
-collFirstItemProcessed :: GenParser ByteString ParseState ()
+collFirstItemProcessed :: GenParser ParseState ()
 collFirstItemProcessed = getState >>= \(bUrl, dUrl, i, pms, s, p, _:cs, ts) ->
                          setState (bUrl, dUrl, i, pms, s, p, False:cs, ts)
 
@@ -503,7 +502,7 @@
 -- in the monad is *not* the value that was popped from the stack, but whether
 -- we are still processing a parent collection or have finished processing
 -- all collections and are no longer in a collection at all.
-finishColl :: GenParser ByteString ParseState Bool
+finishColl :: GenParser ParseState Bool
 finishColl = getState >>= \(bUrl, dUrl, i, pms, s, p, cs, ts) ->
              let cs' = drop 1 cs
              in setState (bUrl, dUrl, i, pms, s, p, cs', ts) >> return (not $ null cs')
@@ -514,7 +513,7 @@
 no = Nothing
 
 -- Update the subject and predicate values of the ParseState to Nothing.
-resetSubjectPredicate :: GenParser ByteString ParseState ()
+resetSubjectPredicate :: GenParser ParseState ()
 resetSubjectPredicate =
   getState >>= \(bUrl, dUrl, n, pms, _, _, cs, ts) ->
   setState (bUrl, dUrl, n, pms, [], [], cs, ts)
@@ -523,7 +522,7 @@
 -- that have non-Nothing values.
 _modifyState :: Maybe (Maybe BaseUrl) -> Maybe (Int -> Int) -> Maybe PrefixMappings ->
                 Maybe Subject -> Maybe Predicate -> Maybe (Seq Triple) ->
-                GenParser ByteString ParseState ()
+                GenParser ParseState ()
 _modifyState mb_bUrl mb_n mb_pms mb_subj mb_pred mb_trps =
   do (_bUrl, _dUrl, _n, _pms, _s, _p, _cs, _ts) <- getState
      setState (fromMaybe _bUrl mb_bUrl,
@@ -535,7 +534,7 @@
               _cs,
               fromMaybe _ts mb_trps)
 
-addTripleForObject :: Object -> GenParser ByteString ParseState ()
+addTripleForObject :: Object -> GenParser ParseState ()
 addTripleForObject obj =
   do (bUrl, dUrl, i, pms, ss, ps, cs, ts) <- getState
      when (null ss) $
@@ -563,7 +562,7 @@
 -- Returns either a @ParseFailure@ or a new RDF containing the parsed triples.
 parseURL' :: forall rdf. (RDF rdf) => 
                  Maybe BaseUrl       -- ^ The optional base URI of the document.
-                 -> Maybe ByteString -- ^ The document URI (i.e., the URI of the document itself); if Nothing, use location URI.
+                 -> Maybe T.Text -- ^ The document URI (i.e., the URI of the document itself); if Nothing, use location URI.
                  -> String           -- ^ The location URI from which to retrieve the Turtle document.
                  -> IO (Either ParseFailure rdf)
                                      -- ^ The parse result, which is either a @ParseFailure@ or the RDF
@@ -575,15 +574,15 @@
 -- than a location URI.
 --
 -- Returns either a @ParseFailure@ or a new RDF containing the parsed triples.
-parseFile' :: forall rdf. (RDF rdf) => Maybe BaseUrl -> Maybe ByteString -> String -> IO (Either ParseFailure rdf)
+parseFile' :: forall rdf. (RDF rdf) => Maybe BaseUrl -> Maybe T.Text -> String -> IO (Either ParseFailure rdf)
 parseFile' bUrl docUrl fpath =
-  B.readFile fpath >>= \bs -> return $ handleResult bUrl (runParser t_turtleDoc initialState (maybe "" B.unpack docUrl) bs)
+  TIO.readFile fpath >>= \bs -> return $ handleResult bUrl (runParser t_turtleDoc initialState (maybe "" t2s docUrl) bs)
   where initialState = (bUrl, docUrl, 1, PrefixMappings Map.empty, [], [], [], Seq.empty)
 
 -- |Parse the given string as a Turtle document. The arguments and return type have the same semantics 
 -- as <parseURL>, except that the last @String@ argument corresponds to the Turtle document itself as
 -- a a string rather than a location URI.
-parseString' :: forall rdf. (RDF rdf) => Maybe BaseUrl -> Maybe ByteString -> ByteString -> Either ParseFailure rdf
+parseString' :: forall rdf. (RDF rdf) => Maybe BaseUrl -> Maybe T.Text -> T.Text -> Either ParseFailure rdf
 parseString' bUrl docUrl ttlStr = handleResult bUrl (runParser t_turtleDoc initialState "" ttlStr)
   where initialState = (bUrl, docUrl, 1, PrefixMappings Map.empty, [], [], [], Seq.empty)
 
diff --git a/src/Text/RDF/RDF4H/TurtleSerializer.hs b/src/Text/RDF/RDF4H/TurtleSerializer.hs
--- a/src/Text/RDF/RDF4H/TurtleSerializer.hs
+++ b/src/Text/RDF/RDF4H/TurtleSerializer.hs
@@ -10,10 +10,9 @@
 import Data.RDF
 import Data.RDF.Namespace
 import Data.RDF.Utils
-
-import Data.ByteString.Lazy.Char8(ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B
-import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import Data.Text.Encoding (encodeUtf8)
+import qualified Data.ByteString.Char8 as B
 import Data.Map(Map)
 import qualified Data.Map as Map
 import Data.List
@@ -24,7 +23,7 @@
 -- Defined so that there are no compiler warnings when trace is not used.
 _debug = trace
 
-data TurtleSerializer = TurtleSerializer (Maybe ByteString) PrefixMappings
+data TurtleSerializer = TurtleSerializer (Maybe T.Text) PrefixMappings
 
 instance RdfSerializer TurtleSerializer where
   hWriteRdf  (TurtleSerializer docUrl pms) h rdf = _writeRdf h docUrl (addPrefixMappings rdf pms False)
@@ -46,7 +45,7 @@
 -- configurable somehow, so that if the user really doesn't want any extra
 -- prefix declarations added, that is possible.
 
-_writeRdf :: RDF rdf => Handle -> Maybe ByteString -> rdf -> IO ()
+_writeRdf :: RDF rdf => Handle -> Maybe T.Text -> rdf -> IO ()
 _writeRdf h mdUrl rdf =
   writeHeader h bUrl pms' >> writeTriples h mdUrl pms' ts >> hPutChar h '\n'
   where
@@ -64,27 +63,27 @@
 writeBase _ Nothing               =
   return ()
 writeBase h (Just (BaseUrl bUrl)) =
-  hPutStr h "@base " >> hPutChar h '<' >> BL.hPutStr h bUrl >> hPutStr h "> ." >> hPutChar h '\n'
+  hPutStr h "@base " >> hPutChar h '<' >> B.hPutStr h (encodeUtf8 bUrl) >> hPutStr h "> ." >> hPutChar h '\n'
 
 writePrefixes :: Handle -> PrefixMappings -> IO ()
 writePrefixes h pms = mapM_ (writePrefix h) (toPMList pms) >> hPutChar h '\n'
 
-writePrefix :: Handle -> (ByteString, ByteString) -> IO ()
+writePrefix :: Handle -> (T.Text, T.Text) -> IO ()
 writePrefix h (pre, uri) =
-  hPutStr h "@prefix " >> BL.hPutStr h pre >> hPutStr h ": " >>
-  hPutChar h '<' >> BL.hPutStr h uri >> hPutStr h "> ." >> hPutChar h '\n'
+  hPutStr h "@prefix " >> B.hPutStr h (encodeUtf8 pre) >> hPutStr h ": " >>
+  hPutChar h '<' >> B.hPutStr h (encodeUtf8 uri) >> hPutStr h "> ." >> hPutChar h '\n'
 
 -- We don't really use the map as a map yet, but we reverse the map anyway so that
 -- it maps from uri to prefix rather than the usual prefix to uri, since we never need
 -- to look anything up by prefix, where as we do use the uri for determining which
 -- prefix to use.
-writeTriples :: Handle -> Maybe ByteString -> PrefixMappings -> Triples -> IO ()
+writeTriples :: Handle -> Maybe T.Text -> PrefixMappings -> Triples -> IO ()
 writeTriples h mdUrl (PrefixMappings pms) ts =
   mapM_ (writeSubjGroup h mdUrl revPms) (groupBy equalSubjects ts)
   where
     revPms = Map.fromList $ map (\(k,v) -> (v,k)) $ Map.toList pms
 
-writeTriple :: Handle -> Maybe ByteString -> PrefixMappings -> Triple -> IO ()
+writeTriple :: Handle -> Maybe T.Text -> PrefixMappings -> Triple -> IO ()
 writeTriple h mdUrl (PrefixMappings pms) t = 
   w subjectOf >> space >> w predicateOf >> space >> w objectOf
   where
@@ -94,7 +93,7 @@
 
 -- Write a group of triples that all have the same subject, with the subject only
 -- being output once, and comma or semi-colon used as appropriate.
-writeSubjGroup :: Handle -> Maybe ByteString -> Map ByteString ByteString -> Triples -> IO ()
+writeSubjGroup :: Handle -> Maybe T.Text -> Map T.Text T.Text -> Triples -> IO ()
 writeSubjGroup _ _    _   []     = return ()
 writeSubjGroup h dUrl pms ts@(t:_) =
   writeNode h dUrl (subjectOf t) pms >> hPutChar h ' ' >>
@@ -107,7 +106,7 @@
 -- Write a group of triples that all have the same subject and the same predicate,
 -- assuming the subject has already been output and only the predicate and objects
 -- need to be written.
-writePredGroup :: Handle -> Maybe ByteString -> Map ByteString ByteString -> Triples -> IO ()
+writePredGroup :: Handle -> Maybe T.Text -> Map T.Text T.Text -> Triples -> IO ()
 writePredGroup _  _       _   []     = return ()
 writePredGroup h  docUrl pms (t:ts) =
   -- The doesn't rule out <> in either the predicate or object (as well as subject), 
@@ -116,58 +115,58 @@
   writeNode h docUrl (objectOf t) pms >>
   mapM_ (\t -> hPutStr h ", " >> writeNode h docUrl (objectOf t) pms) ts
 
-writeNode :: Handle -> Maybe ByteString -> Node -> Map ByteString ByteString -> IO ()
+writeNode :: Handle -> Maybe T.Text -> Node -> Map T.Text T.Text -> IO ()
 writeNode h mdUrl node prefixes =
   case node of
-    (UNode fs)  -> let currUri = B.reverse $ value fs
+    (UNode bs)  -> let currUri = T.reverse bs
                    in case mdUrl of
                         Nothing  -> writeUNodeUri h currUri prefixes
                         Just url -> if url == currUri then hPutStr h "<>" else writeUNodeUri h currUri prefixes
-    (BNode gId) -> hPutStrRev h (value gId)
+    (BNode gId) -> hPutStrRev h gId
     (BNodeGen i)-> putStr "_:genid" >> hPutStr h (show i)
     (LNode n)   -> writeLValue h n prefixes
 
-writeUNodeUri :: Handle -> ByteString -> Map ByteString ByteString -> IO ()
+writeUNodeUri :: Handle -> T.Text -> Map T.Text T.Text -> IO ()
 writeUNodeUri h uri prefixes =
   case mapping of
-    Nothing                 -> hPutChar h '<' >> BL.hPutStr h uri >> hPutChar h '>'
-    (Just (pre, localName)) -> BL.hPutStr h pre >> hPutChar h ':' >> BL.hPutStr h localName
+    Nothing                 -> hPutChar h '<' >> B.hPutStr h (encodeUtf8 uri) >> hPutChar h '>'
+    (Just (pre, localName)) -> B.hPutStr h (encodeUtf8 pre) >> hPutChar h ':' >> B.hPutStr h (encodeUtf8 localName)
   where
     mapping         = findMapping prefixes uri
 
 -- Print prefix mappings to stdout for debugging.
-_debugPMs     :: Map ByteString ByteString -> IO ()
-_debugPMs pms =  mapM_ (\(k, v) -> B.putStr k >> putStr "__" >> B.putStrLn v) (Map.toList pms)
+_debugPMs     :: Map T.Text T.Text -> IO ()
+_debugPMs pms =  mapM_ (\(k, v) -> B.putStr (encodeUtf8 k) >> putStr "__" >> B.putStrLn (encodeUtf8 v)) (Map.toList pms)
 
 -- Expects a map from uri to prefix, and returns the (prefix, uri_expansion)
 -- from the mappings such that uri_expansion is a prefix of uri, or Nothing if
 -- there is no such mapping. This function does a linear-time search over the 
 -- map, but the prefix mappings should always be very small, so it's okay for now.
-findMapping :: Map ByteString ByteString -> ByteString -> Maybe (ByteString, ByteString)
+findMapping :: Map T.Text T.Text -> T.Text -> Maybe (T.Text, T.Text)
 findMapping pms uri =
   case mapping of
     Nothing     -> Nothing
-    Just (u, p) -> Just (p, B.drop (B.length u) uri) -- empty localName is permitted
+    Just (u, p) -> Just (p, T.drop (T.length u) uri) -- empty localName is permitted
   where
-    mapping        = find (\(k, _) -> B.isPrefixOf k uri) (Map.toList pms)
+    mapping        = find (\(k, _) -> T.isPrefixOf k uri) (Map.toList pms)
 
 --_testPms = Map.fromList [(s2b "http://example.com/ex#", s2b "eg")]
 
-writeLValue :: Handle -> LValue -> Map ByteString ByteString -> IO ()
+writeLValue :: Handle -> LValue -> Map T.Text T.Text -> IO ()
 writeLValue h lv pms =
   case lv of
     (PlainL lit)       -> writeLiteralString h lit
     (PlainLL lit lang) -> writeLiteralString h lit >>
                             hPutStr h "@" >>
-                            BL.hPutStr h lang
+                            B.hPutStr h (encodeUtf8 lang)
     (TypedL lit dtype) -> writeLiteralString h lit >>
                             hPutStr h "^^" >>
-                            writeUNodeUri h (B.reverse $ value dtype) pms
+                            writeUNodeUri h (T.reverse dtype) pms
 
-writeLiteralString:: Handle -> ByteString -> IO ()
+writeLiteralString:: Handle -> T.Text -> IO ()
 writeLiteralString h bs =
   do hPutChar h '"'
-     B.foldl' writeChar (return True) bs
+     T.foldl' writeChar (return True) bs
      hPutChar h '"'
   where
     writeChar :: IO Bool -> Char -> IO Bool
diff --git a/src/Text/RDF/RDF4H/XmlParser.hs b/src/Text/RDF/RDF4H/XmlParser.hs
--- a/src/Text/RDF/RDF4H/XmlParser.hs
+++ b/src/Text/RDF/RDF4H/XmlParser.hs
@@ -9,7 +9,7 @@
 import qualified Data.Map as Map
 import Control.Arrow
 import Text.XML.HXT.Core
-import Data.ByteString.Lazy.Char8(ByteString)
+import qualified Data.Text as T
 import Data.String.Utils
 
 -- TODO: Create instance:
@@ -27,41 +27,41 @@
                                }
   deriving(Show)
 
--- |Parse a xml ByteString to an RDF representation
+-- |Parse a xml T.Text to an RDF representation
 parseXmlRDF :: forall rdf. (RDF rdf)
             => Maybe BaseUrl           -- ^ The base URL for the RDF if required
-            -> Maybe ByteString        -- ^ DocUrl: The request URL for the RDF if available
-            -> ByteString              -- ^ The contents to parse
+            -> Maybe T.Text        -- ^ DocUrl: The request URL for the RDF if available
+            -> T.Text              -- ^ The contents to parse
             -> Either ParseFailure rdf -- ^ The RDF representation of the triples or ParseFailure
 parseXmlRDF bUrl dUrl xmlStr = case runParseArrow of
                                 (_,r:_) -> Right r
                                 _ -> Left (ParseFailure "XML parsing failed")
-  where runParseArrow = runSLA (xread >>> addMetaData bUrl dUrl >>> getRDF) initState (b2s xmlStr)
+  where runParseArrow = runSLA (xread >>> addMetaData bUrl dUrl >>> getRDF) initState (t2s xmlStr)
         initState = GParseState { stateGenId = 0 }
 
 -- |Add a root tag to a given XmlTree to appear as if it was read from a readDocument function
-addMetaData :: (ArrowXml a) => Maybe BaseUrl -> Maybe ByteString -> a XmlTree XmlTree
+addMetaData :: (ArrowXml a) => Maybe BaseUrl -> Maybe T.Text -> a XmlTree XmlTree
 addMetaData bUrlM dUrlM = mkelem "/"
                         ( [ sattr "transfer-Message" "OK"
                           , sattr "transfer-MimeType" "text/rdf"
                           ] ++ mkSource dUrlM ++ mkBase bUrlM
                         )
                         [ arr id ]
-  where mkSource (Just dUrl) = [ sattr "source" (b2s dUrl) ]
+  where mkSource (Just dUrl) = [ sattr "source" (t2s dUrl) ]
         mkSource Nothing = []
-        mkBase (Just (BaseUrl bUrl)) = [ sattr "transfer-URI" (b2s bUrl) ]
+        mkBase (Just (BaseUrl bUrl)) = [ sattr "transfer-URI" (t2s bUrl) ]
         mkBase Nothing = []
 
 -- |Arrow that translates HXT XmlTree to an RDF representation
 getRDF :: forall rdf a. (RDF rdf, ArrowXml a, ArrowState GParseState a) => a XmlTree rdf
 getRDF = proc xml -> do
-              rdf <- hasName "rdf:RDF" <<< isElem <<< getChildren         -< xml
-              bUrl <- arr (BaseUrl . s2b) <<< ((getAttrValue0 "xml:base" <<< isElem <<< getChildren) `orElse` getAttrValue "transfer-URI") -< xml
-              prefixMap <- arr toPrefixMap <<< toAttrMap                  -< rdf
-              triples <- parseDescription' >. id -< (bUrl, rdf)
-              returnA -< mkRdf triples (Just bUrl) prefixMap
+            rdf <- hasName "rdf:RDF" <<< isElem <<< getChildren         -< xml
+            bUrl <- arr (BaseUrl . s2t) <<< ((getAttrValue0 "xml:base" <<< isElem <<< getChildren) `orElse` getAttrValue "transfer-URI") -< xml
+            prefixMap <- arr toPrefixMap <<< toAttrMap                  -< rdf
+            triples <- parseDescription' >. id -< (bUrl, rdf)
+            returnA -< mkRdf triples (Just bUrl) prefixMap
   where toAttrMap = (getAttrl >>> (getName &&& (getChildren >>> getText))) >. id
-        toPrefixMap = PrefixMappings . Map.fromList . map (\(n, m) -> (s2b (drop 6 n), s2b m)) . filter (startswith "xmlns:" . fst)
+        toPrefixMap = PrefixMappings . Map.fromList . map (\(n, m) -> (s2t (drop 6 n), s2t m)) . filter (startswith "xmlns:" . fst)
 
 -- |Read the initial state from an rdf element
 parseDescription' :: forall a. (ArrowXml a, ArrowState GParseState a) => a (BaseUrl, XmlTree) Triple
@@ -79,9 +79,9 @@
                    <+> (second (neg (hasName "rdf:Description")) >>> arr2A readTypeTriple))
                >>. replaceLiElems [] (1 :: Int)
   where readTypeTriple :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Triple
-        readTypeTriple state = getName >>> arr (Triple (stateSubject state) rdfType . unode . s2b)
-        replaceLiElems acc n (Triple s p o : rest) | p == (unode . s2b) "rdf:li" =
-            replaceLiElems (Triple s ((unode . s2b) ("rdf:_" ++ show n)) o : acc) (n + 1) rest
+        readTypeTriple state = getName >>> arr (Triple (stateSubject state) rdfType . unode . s2t)
+        replaceLiElems acc n (Triple s p o : rest) | p == (unode . s2t) "rdf:li" =
+            replaceLiElems (Triple s ((unode . s2t) ("rdf:_" ++ show n)) o : acc) (n + 1) rest
         replaceLiElems acc n (Triple s p o : rest) = replaceLiElems (Triple s p o : acc) n rest
         replaceLiElems acc _ [] = acc
 
@@ -89,13 +89,13 @@
 parseAsResource :: forall a. (ArrowXml a, ArrowState GParseState a) => Node -> a (LParseState, XmlTree) Triple
 parseAsResource n = updateState
     >>>     (arr2A parsePredicatesFromAttr
-        <+> (second getName >>> arr (\(s, p) -> Triple (stateSubject s) ((unode . s2b) p) n))
+        <+> (second getName >>> arr (\(s, p) -> Triple (stateSubject s) ((unode . s2t) p) n))
         <+> (arr (\s -> s { stateSubject = n }) *** (getChildren >>> isElem) >>> parsePredicatesFromChildren))
 
 -- |Read the attributes of an rdf:Description element.  These correspond to the Predicate Object pairs of the Triple
 parsePredicatesFromAttr :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Triple
 parsePredicatesFromAttr state = getAttrl
-    >>> (getName >>> neg isMetaAttr >>> mkUNode) &&& (getChildren >>> getText >>> arr (lnode . plainL . s2b))
+    >>> (getName >>> neg isMetaAttr >>> mkUNode) &&& (getChildren >>> getText >>> arr (lnode . plainL . s2t))
     >>> arr (attachSubject (stateSubject state))
 
 -- | Arrow to determine if special processing is required for an attribute
@@ -122,10 +122,10 @@
         , this :-> defaultA
         ]
   where defaultA = proc (state, predXml) -> do
-                         p <- arr(unode . s2b) <<< getName -< predXml
+                         p <- arr(unode . s2t) <<< getName -< predXml
                          t <- arr2A (arr2A . parseObjectsFromChildren) <<< second (second getChildren) -< (state, (p, predXml))
                          returnA -< t
-        parsePredicateAttr n = (second getName >>> arr (\(s, p) -> Triple (stateSubject s) ((unode . s2b) p) n))
+        parsePredicateAttr n = (second getName >>> arr (\(s, p) -> Triple (stateSubject s) ((unode . s2t) p) n))
                            <+> (first (arr (\s -> s { stateSubject = n })) >>> arr2A parsePredicatesFromAttr)
         hasPredicateAttr = getAttrl >>> neg (getName >>> isMetaAttr)
 
@@ -158,7 +158,7 @@
 updateState = ifA (second (hasAttr "xml:lang")) (arr2A readLang) (arr id)
           >>> ifA (second (hasAttr "xml:base")) (arr2A readBase) (arr id)
   where readLang state = (getAttrValue0 "xml:lang" >>> arr (\lang -> state { stateLang = Just lang } ) ) &&& arr id
-        readBase state = (getAttrValue0 "xml:base" >>> arr (\base -> state { stateBaseUrl = (BaseUrl . s2b) base } ) ) &&& arr id
+        readBase state = (getAttrValue0 "xml:base" >>> arr (\base -> state { stateBaseUrl = (BaseUrl . s2t) base } ) ) &&& arr id
 
 -- |Read a Triple with an rdf:parseType of Literal
 parseAsLiteralTriple :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Triple
@@ -177,7 +177,7 @@
 
 -- |Read a Triple and it's type when rdf:datatype is available
 getTypedTriple :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Triple
-getTypedTriple state = nameToUNode &&& (attrExpandURI state "rdf:datatype" &&& xshow getChildren >>> arr (\(t, v) -> mkTypedLiteralNode (mkFastString (s2b t)) v))
+getTypedTriple state = nameToUNode &&& (attrExpandURI state "rdf:datatype" &&& xshow getChildren >>> arr (\(t, v) -> mkTypedLiteralNode ( (s2t t)) v))
     >>> arr (attachSubject (stateSubject state))
 
 getResourceTriple :: forall a. (ArrowXml a, ArrowState GParseState a)
@@ -187,53 +187,53 @@
 
 getNodeIdTriple :: forall a. (ArrowXml a, ArrowState GParseState a)
                 => LParseState -> a XmlTree Triple
-getNodeIdTriple state = nameToUNode &&& (getAttrValue "rdf:nodeID" >>> arr (bnode . s2b))
+getNodeIdTriple state = nameToUNode &&& (getAttrValue "rdf:nodeID" >>> arr (bnode . s2t))
     >>> arr (attachSubject (stateSubject state))
 
 -- |Read a Node from the "rdf:about" property or generate a blank node
 mkNode :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Node
 mkNode state = choiceA [ hasAttr "rdf:about" :-> (attrExpandURI state "rdf:about" >>> mkUNode)
                        , hasAttr "rdf:resource" :-> (attrExpandURI state "rdf:resource" >>> mkUNode)
-                       , hasAttr "rdf:nodeID" :-> (getAttrValue "rdf:nodeID" >>> arr (bnode . s2b))
+                       , hasAttr "rdf:nodeID" :-> (getAttrValue "rdf:nodeID" >>> arr (bnode . s2t))
                        , hasAttr "rdf:ID" :-> mkRelativeNode state
                        , this :-> mkBlankNode
                        ]
 
-rdfXmlLiteral = (mkFastString . s2b) "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"
-rdfFirst = (unode . s2b) "rdf:first"
-rdfRest = (unode . s2b) "rdf:rest"
-rdfNil = (unode . s2b) "rdf:nil"
-rdfType = (unode . s2b) "rdf:type"
-rdfStatement = (unode . s2b) "rdf:Statement"
-rdfSubject = (unode . s2b) "rdf:subject"
-rdfPredicate = (unode . s2b) "rdf:predicate"
-rdfObject = (unode . s2b) "rdf:object"
+rdfXmlLiteral = (s2t) "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"
+rdfFirst = (unode . s2t) "rdf:first"
+rdfRest = (unode . s2t) "rdf:rest"
+rdfNil = (unode . s2t) "rdf:nil"
+rdfType = (unode . s2t) "rdf:type"
+rdfStatement = (unode . s2t) "rdf:Statement"
+rdfSubject = (unode . s2t) "rdf:subject"
+rdfPredicate = (unode . s2t) "rdf:predicate"
+rdfObject = (unode . s2t) "rdf:object"
 
 nameToUNode :: forall a. (ArrowXml a) => a XmlTree Node
 nameToUNode = getName >>> mkUNode
 
 attrExpandURI :: forall a. (ArrowXml a) => LParseState -> String -> a XmlTree String
 attrExpandURI state attr = getAttrValue attr &&& baseUrl >>> expandURI
-  where baseUrl = constA (case stateBaseUrl state of BaseUrl b -> b2s b)
+  where baseUrl = constA (case stateBaseUrl state of BaseUrl b -> t2s b)
 
 -- |Make a UNode from an absolute string
 mkUNode :: forall a. (Arrow a) => a String Node
-mkUNode = arr (unode . s2b)
+mkUNode = arr (unode . s2t)
 
 -- |Make a UNode from a rdf:ID element, expanding relative URIs
 mkRelativeNode :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Node
 mkRelativeNode s = (getAttrValue "rdf:ID" >>> arr (\x -> '#':x)) &&& baseUrl
-    >>> expandURI >>> arr (unode . s2b)
-  where baseUrl = constA (case stateBaseUrl s of BaseUrl b -> b2s b)
+    >>> expandURI >>> arr (unode . s2t)
+  where baseUrl = constA (case stateBaseUrl s of BaseUrl b -> t2s b)
 
 -- |Make a literal node with the given type and content
-mkTypedLiteralNode :: FastString -> String -> Node
-mkTypedLiteralNode t content = lnode (typedL (s2b content) t)
+mkTypedLiteralNode :: T.Text -> String -> Node
+mkTypedLiteralNode t content = lnode (typedL (s2t content) t)
 
 -- |Use the given state to create a literal node
 mkLiteralNode :: LParseState -> String -> Node
-mkLiteralNode (LParseState _ (Just lang) _) content = lnode (plainLL (s2b content) (s2b lang))
-mkLiteralNode (LParseState _ Nothing _) content = (lnode . plainL . s2b) content
+mkLiteralNode (LParseState _ (Just lang) _) content = lnode (plainLL (s2t content) (s2t lang))
+mkLiteralNode (LParseState _ Nothing _) content = (lnode . plainL . s2t) content
 
 -- |Generate an RDF blank node with incrementing IDs from the arrow state
 mkBlankNode :: forall a b. (ArrowState GParseState a) => a b Node
diff --git a/testsuite/tests/Test.hs b/testsuite/tests/Test.hs
--- a/testsuite/tests/Test.hs
+++ b/testsuite/tests/Test.hs
@@ -1,8 +1,6 @@
 module Main where
 
 import Test.Framework (defaultMain)
-import Test.Framework.Providers.HUnit
-import Test.Framework.Providers.QuickCheck2 (testProperty)
 import Text.RDF.RDF4H.TurtleParser_ConformanceTest as TurtleParser
 import qualified Data.RDF.TriplesGraph_Test as TriplesGraph
 import qualified Data.RDF.MGraph_Test as MGraph
@@ -11,7 +9,7 @@
 main :: IO () 
 main = defaultMain (  TriplesGraph.tests
                    ++ MGraph.tests
-                   -- ++ TurtleParser.test -- TODO: Implement TurtleParses `tests'
+                   ++ TurtleParser.tests
                    ++ XmlParser.tests
                    )
 
