diff --git a/Codec/Binary/Base91.hs b/Codec/Binary/Base91.hs
--- a/Codec/Binary/Base91.hs
+++ b/Codec/Binary/Base91.hs
@@ -1,12 +1,63 @@
 -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.
 -- Informed by Mario Rodriguez's C++ implementation.
 
-module Codec.Binary.Base91 (decoding, encoding) where
+module Codec.Binary.Base91 (alphabet, decodeBy, encodeBy) where
 
+import Data.Bits ((.&.), (.|.), shiftL, shiftR)
+import Data.Char (ord)
 import Data.Word (Word8)
 
-encoding :: [Char]
-encoding = [
+
+type LeftFold a b c = (a -> b -> a) -> a -> c -> a
+
+
+encodeBy :: LeftFold (Int, Int, o) Word8 s -> (o -> [Char] -> o) -> o -> s -> o
+encodeBy fold append empty source = g . fold f (0, 0, empty) $ source where
+
+--f :: (Int, Int, o) -> Word8 -> (Int, Int, o)
+  f (queue, nbits, output) w =
+    let queue' = queue .|. (fromIntegral w `shiftL` nbits)
+        nbits' = nbits + 8
+    in if nbits' <= 13 then (queue', nbits', output) else
+      let val  = queue' .&. 8191
+          val' = queue' .&. 16383
+          (v, q, n)   = if val > 88
+            then (val,  queue' `shiftR` 13, nbits' - 13)
+            else (val', queue' `shiftR` 14, nbits' - 14)
+          trail       = [alphabet !! (v `mod` 91),
+                         alphabet !! (v `div` 91)]
+      in (q, n, append output trail)
+
+--g :: (Int, Int, o) -> o
+  g (_,     0,     output) = output
+  g (queue, nbits, output) = append output (y:z)
+    where y = alphabet !! (queue `mod` 91)
+          z | nbits > 7 || queue > 90 = [alphabet !! (queue `div` 91)]
+            | otherwise               = []
+
+decodeBy :: LeftFold (Int, Int, Int, o) Char s -> (o -> [Word8] -> o) -> o -> s -> o
+decodeBy fold append empty source = g . fold f (0, 0, -1, empty) $ source where
+
+--f :: (Int, Int, Int, o) -> Char -> (Int, Int, Int, o)
+  f (queue, nbits, val, output) c =
+    let d = fromIntegral $ octets !! ord c
+     in if d   == 91 then (queue, nbits, val, output) else
+        if val == -1 then (queue, nbits, d,   output) else
+            let v = val + (d * 91)
+                q = queue .|. (v `shiftL` nbits)
+                n = nbits + (if (v .&. 8191) > 88 then 13 else 14)
+                (queue', nbits', trail) = if n - 8 > 7
+                  then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])
+                  else (q `shiftR` 8,  n - 8,  [q])
+             in (queue', nbits', -1, append output $ map fromIntegral trail)
+
+--g :: (Int, Int, Int, o) -> o
+  g (_,     _,     -1,  output) = output
+  g (queue, nbits, val, output) = append output [fromIntegral $ queue .|. (val `shiftL` nbits)]
+
+-- | The list of valid characters within a Base91-encoded string.
+alphabet :: [Char]
+alphabet = [
   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
   'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
   'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
@@ -15,8 +66,8 @@
   '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
   '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"']
 
-decoding :: [Word8]
-decoding = [
+octets :: [Word8]
+octets = [
   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
   91, 62, 90, 63, 64, 65, 66, 91, 67, 68, 69, 70, 71, 91, 72, 73,
diff --git a/Codec/Binary/Base91/ByteString.hs b/Codec/Binary/Base91/ByteString.hs
--- a/Codec/Binary/Base91/ByteString.hs
+++ b/Codec/Binary/Base91/ByteString.hs
@@ -1,58 +1,15 @@
 -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.
--- Informed by Mario Rodriguez's C++ implementation.
 
 module Codec.Binary.Base91.ByteString (decode, encode) where
 
-import qualified Codec.Binary.Base91 as B91
-import Data.Bits ((.&.), (.|.), shiftL, shiftR)
-import Data.Char (ord)
-import Data.List (foldl')
-import Data.Word (Word8)
-import Data.ByteString (ByteString)
+import Codec.Binary.Base91 (decodeBy, encodeBy)
 import qualified Data.ByteString as BS
+import qualified Data.List as L
 
 -- | Encodes octets ('ByteString') to a '[Char]' in Base91; the opposite of 'decode'.
-encode :: ByteString -> [Char]
-encode = g . BS.foldl' f (0, 0, []) where
-
-  f :: (Int, Int, [Char]) -> Word8 -> (Int, Int, [Char])
-  f (queue, nbits, cs) w =
-    let queue' = queue .|. (fromIntegral w `shiftL` nbits)
-        nbits' = nbits + 8
-    in if nbits' <= 13 then (queue', nbits', cs) else
-      let val  = queue' .&. 8191
-          val' = queue' .&. 16383
-          (v, q, n)   = if val > 88
-            then (val,  queue' `shiftR` 13, nbits' - 13)
-            else (val', queue' `shiftR` 14, nbits' - 14)
-          trail       = [B91.encoding !! (v `mod` 91),
-                         B91.encoding !! (v `div` 91)]
-      in (q, n, cs ++ trail)
-
-  g :: (Int, Int, [Char]) -> [Char]
-  g (_,     0,     cs) = cs
-  g (queue, nbits, cs) = cs ++ [y] ++ z
-    where y = B91.encoding !! (queue `mod` 91)
-          z | nbits > 7 || queue > 90 = [B91.encoding !! (queue `div` 91)]
-            | otherwise               = []
+encode :: BS.ByteString -> [Char]
+encode = encodeBy BS.foldl' (++) []
 
 -- | Decodes octets ('ByteString') from a '[Char]' in Base91; the opposite of 'encode'.
-decode :: [Char] -> ByteString
-decode = g . foldl' f (0, 0, -1, BS.empty) where
-
-  f :: (Int, Int, Int, ByteString) -> Char -> (Int, Int, Int, ByteString)
-  f (queue, nbits, val, bs) c =
-    let d = fromIntegral $ B91.decoding !! ord c
-     in if d   == 91 then (queue, nbits, val, bs) else
-        if val == -1 then (queue, nbits, d,   bs) else
-            let v = val + (d * 91)
-                q = queue .|. (v `shiftL` nbits)
-                n = nbits + (if (v .&. 8191) > 88 then 13 else 14)
-                (queue', nbits', trail) = if n - 8 > 7
-                  then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])
-                  else (q `shiftR` 8,  n - 8,  [q])
-             in (queue', nbits', -1, BS.append bs $ BS.pack (map fromIntegral trail))
-
-  g :: (Int, Int, Int, ByteString) -> ByteString
-  g (_,     _,     -1,  bs) = bs
-  g (queue, nbits, val, bs) = BS.snoc bs (fromIntegral $ queue .|. (val `shiftL` nbits))
+decode :: [Char] -> BS.ByteString
+decode = decodeBy L.foldl' (\bs -> BS.append bs . BS.pack) BS.empty
diff --git a/Codec/Binary/Base91/Efficient.hs b/Codec/Binary/Base91/Efficient.hs
--- a/Codec/Binary/Base91/Efficient.hs
+++ b/Codec/Binary/Base91/Efficient.hs
@@ -1,59 +1,15 @@
 -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.
--- Informed by Mario Rodriguez's C++ implementation.
 
 module Codec.Binary.Base91.Efficient (decode, encode) where
 
-import qualified Codec.Binary.Base91 as B91
-import Data.Bits ((.&.), (.|.), shiftL, shiftR)
-import Data.Char (ord)
-import Data.Word (Word8)
-import Data.ByteString (ByteString)
+import Codec.Binary.Base91 (decodeBy, encodeBy)
 import qualified Data.ByteString as BS
-import Data.Text (Text)
 import qualified Data.Text as T
 
 -- | Encodes octets ('ByteString') to 'Text' in Base91; the opposite of 'decode'.
-encode :: ByteString -> Text
-encode = g . BS.foldl' f (0, 0, T.empty) where
-
-  f :: (Int, Int, Text) -> Word8 -> (Int, Int, Text)
-  f (queue, nbits, t) w =
-    let queue' = queue .|. (fromIntegral w `shiftL` nbits)
-        nbits' = nbits + 8
-    in if nbits' <= 13 then (queue', nbits', t) else
-      let val  = queue' .&. 8191
-          val' = queue' .&. 16383
-          (v, q, n)   = if val > 88
-            then (val,  queue' `shiftR` 13, nbits' - 13)
-            else (val', queue' `shiftR` 14, nbits' - 14)
-          trail       = [B91.encoding !! (v `mod` 91),
-                         B91.encoding !! (v `div` 91)]
-      in (q, n, T.append t (T.pack trail))
-
-  g :: (Int, Int, Text) -> Text
-  g (_,     0,     t) = t
-  g (queue, nbits, t) = T.append t (T.pack $ [y] ++ z)
-    where y = B91.encoding !! (queue `mod` 91)
-          z | nbits > 7 || queue > 90 = [B91.encoding !! (queue `div` 91)]
-            | otherwise               = []
+encode :: BS.ByteString -> T.Text
+encode = encodeBy BS.foldl' (\t -> T.append t . T.pack) T.empty
 
 -- | Decodes octets ('ByteString') from 'Text' in Base91; the opposite of 'encode'.
-decode :: Text -> ByteString
-decode = g . T.foldl' f (0, 0, -1, BS.empty) where
-
-  f :: (Int, Int, Int, ByteString) -> Char -> (Int, Int, Int, ByteString)
-  f (queue, nbits, val, bs) c =
-    let d = fromIntegral $ B91.decoding !! ord c
-     in if d   == 91 then (queue, nbits, val, bs) else
-        if val == -1 then (queue, nbits, d,   bs) else
-            let v = val + (d * 91)
-                q = queue .|. (v `shiftL` nbits)
-                n = nbits + (if (v .&. 8191) > 88 then 13 else 14)
-                (queue', nbits', trail) = if n - 8 > 7
-                  then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])
-                  else (q `shiftR` 8,  n - 8,  [q])
-             in (queue', nbits', -1, BS.append bs $ BS.pack (map fromIntegral trail))
-
-  g :: (Int, Int, Int, ByteString) -> ByteString
-  g (_,     _,     -1,  bs) = bs
-  g (queue, nbits, val, bs) = BS.snoc bs (fromIntegral $ queue .|. (val `shiftL` nbits))
+decode :: T.Text -> BS.ByteString
+decode = decodeBy T.foldl' (\bs -> BS.append bs . BS.pack) BS.empty
diff --git a/Codec/Binary/Base91/String.hs b/Codec/Binary/Base91/String.hs
--- a/Codec/Binary/Base91/String.hs
+++ b/Codec/Binary/Base91/String.hs
@@ -1,56 +1,15 @@
 -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.
--- Informed by Mario Rodriguez's C++ implementation.
 
 module Codec.Binary.Base91.String (decode, encode) where
 
-import qualified Codec.Binary.Base91 as B91
-import Data.Bits ((.&.), (.|.), shiftL, shiftR)
-import Data.Char (ord)
-import Data.List (foldl')
-import Data.Word (Word8)
+import Codec.Binary.Base91 (decodeBy, encodeBy)
+import qualified Data.List as L
+import qualified Data.Word as W
 
 -- | Encodes octets ('[Word8]') to a 'String' in Base91; the opposite of 'decode'.
-encode :: [Word8] -> String
-encode = g . foldl' f (0, 0, []) where
-
-  f :: (Int, Int, [Char]) -> Word8 -> (Int, Int, [Char])
-  f (queue, nbits, cs) w =
-    let queue' = queue .|. (fromIntegral w `shiftL` nbits)
-        nbits' = nbits + 8
-    in if nbits' <= 13 then (queue', nbits', cs) else
-      let val  = queue' .&. 8191
-          val' = queue' .&. 16383
-          (v, q, n)   = if val > 88
-            then (val,  queue' `shiftR` 13, nbits' - 13)
-            else (val', queue' `shiftR` 14, nbits' - 14)
-          trail       = [B91.encoding !! (v `mod` 91),
-                         B91.encoding !! (v `div` 91)]
-      in (q, n, cs ++ trail)
-
-  g :: (Int, Int, [Char]) -> [Char]
-  g (_,     0,     cs) = cs
-  g (queue, nbits, cs) = cs ++ [y] ++ z
-    where y = B91.encoding !! (queue `mod` 91)
-          z | nbits > 7 || queue > 90 = [B91.encoding !! (queue `div` 91)]
-            | otherwise               = []
+encode :: [W.Word8] -> String
+encode = encodeBy L.foldl' (++) []
 
 -- | Decodes octets ('[Word8]') from a 'String' in Base91; the opposite of 'encode'.
-decode :: String -> [Word8]
-decode = g . foldl' f (0, 0, -1, []) where
-
-  f :: (Int, Int, Int, [Word8]) -> Char -> (Int, Int, Int, [Word8])
-  f (queue, nbits, val, ws) c =
-    let d = fromIntegral $ B91.decoding !! ord c
-     in if d   == 91 then (queue, nbits, val, ws) else
-        if val == -1 then (queue, nbits, d,   ws) else
-            let v = val + (d * 91)
-                q = queue .|. (v `shiftL` nbits)
-                n = nbits + (if (v .&. 8191) > 88 then 13 else 14)
-                (queue', nbits', trail) = if n - 8 > 7
-                  then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])
-                  else (q `shiftR` 8,  n - 8,  [q])
-             in (queue', nbits', -1, ws ++ map fromIntegral trail)
-
-  g :: (Int, Int, Int, [Word8]) -> [Word8]
-  g (_,     _,     -1,  ws) = ws
-  g (queue, nbits, val, ws) = ws ++ [fromIntegral $ queue .|. (val `shiftL` nbits)]
+decode :: String -> [W.Word8]
+decode = decodeBy L.foldl' (++) []
diff --git a/Codec/Binary/Base91/Text.hs b/Codec/Binary/Base91/Text.hs
--- a/Codec/Binary/Base91/Text.hs
+++ b/Codec/Binary/Base91/Text.hs
@@ -1,58 +1,16 @@
 -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.
--- Informed by Mario Rodriguez's C++ implementation.
 
 module Codec.Binary.Base91.Text (decode, encode) where
 
-import qualified Codec.Binary.Base91 as B91
-import Data.Bits ((.&.), (.|.), shiftL, shiftR)
-import Data.Char (ord)
-import Data.List (foldl')
-import Data.Word (Word8)
-import Data.Text (Text)
+import Codec.Binary.Base91 (decodeBy, encodeBy)
+import qualified Data.List as L
 import qualified Data.Text as T
+import qualified Data.Word as W
 
 -- | Encodes octets ('[Word8]') to 'Text' in Base91; the opposite of 'decode'.
-encode :: [Word8] -> Text
-encode = g . foldl' f (0, 0, T.empty) where
-
-  f :: (Int, Int, Text) -> Word8 -> (Int, Int, Text)
-  f (queue, nbits, t) w =
-    let queue' = queue .|. (fromIntegral w `shiftL` nbits)
-        nbits' = nbits + 8
-    in if nbits' <= 13 then (queue', nbits', t) else
-      let val  = queue' .&. 8191
-          val' = queue' .&. 16383
-          (v, q, n)   = if val > 88
-            then (val,  queue' `shiftR` 13, nbits' - 13)
-            else (val', queue' `shiftR` 14, nbits' - 14)
-          trail       = [B91.encoding !! (v `mod` 91),
-                         B91.encoding !! (v `div` 91)]
-      in (q, n, T.append t (T.pack trail))
-
-  g :: (Int, Int, Text) -> Text
-  g (_,     0,     t) = t
-  g (queue, nbits, t) = T.append t (T.pack $ [y] ++ z)
-    where y = B91.encoding !! (queue `mod` 91)
-          z | nbits > 7 || queue > 90 = [B91.encoding !! (queue `div` 91)]
-            | otherwise               = []
+encode :: [W.Word8] -> T.Text
+encode = encodeBy L.foldl' (\t -> T.append t . T.pack) T.empty
 
 -- | Decodes octets ('[Word8]') from 'Text' in Base91; the opposite of 'encode'.
-decode :: Text -> [Word8]
-decode = g . T.foldl' f (0, 0, -1, []) where
-
-  f :: (Int, Int, Int, [Word8]) -> Char -> (Int, Int, Int, [Word8])
-  f (queue, nbits, val, ws) c =
-    let d = fromIntegral $ B91.decoding !! ord c
-     in if d   == 91 then (queue, nbits, val, ws) else
-        if val == -1 then (queue, nbits, d,   ws) else
-            let v = val + (d * 91)
-                q = queue .|. (v `shiftL` nbits)
-                n = nbits + (if (v .&. 8191) > 88 then 13 else 14)
-                (queue', nbits', trail) = if n - 8 > 7
-                  then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])
-                  else (q `shiftR` 8,  n - 8,  [q])
-             in (queue', nbits', -1, ws ++ map fromIntegral trail)
-
-  g :: (Int, Int, Int, [Word8]) -> [Word8]
-  g (_,     _,     -1,  ws) = ws
-  g (queue, nbits, val, ws) = ws ++ [fromIntegral $ queue .|. (val `shiftL` nbits)]
+decode :: T.Text -> [W.Word8]
+decode = decodeBy T.foldl' (++) []
diff --git a/base91.cabal b/base91.cabal
--- a/base91.cabal
+++ b/base91.cabal
@@ -1,10 +1,13 @@
 Name:                  base91
-Version:               0.1.0
+Version:               0.1.1
 Author:                Alvaro J. Genial
 Maintainer:            ajg
 Homepage:              https://github.com/ajg/base91
 Synopsis:              A Base91 encoder & decoder
-Description:           An implementation of Base91 encoding & decoding of bytes to/from strings.
+Description:           An implementation of Base91 encoding & decoding of arbitrary bytes (octets)
+                       to/from characters (all in the ASCII printable range; it includes support for
+                       plain Strings, as well as optional support for ByteString and/or Text; see
+                       the Flags section for details.
 License:               MIT
 License-File:          LICENSE.md
 Category:              Codec
@@ -21,8 +24,7 @@
 
 Library
   Build-Depends:       base >= 4 && < 5
-  Exposed-Modules:     Codec.Binary.Base91.String
-  Other-Modules:       Codec.Binary.Base91
+  Exposed-Modules:     Codec.Binary.Base91, Codec.Binary.Base91.String
 
   if flag(ByteString)
     Build-Depends:     bytestring
