diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.9.0.0
+
+- Added `split()` builtin
+- Added support for byte arrays, represented as `ByteString` on the Haskell
+  side
+
 ## 0.8.4.0
 
 - Added builtin `apply`, making it possible to pass argument lists as arrays
diff --git a/ginger.cabal b/ginger.cabal
--- a/ginger.cabal
+++ b/ginger.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                ginger
-version:             0.9.1.0
+version:             0.10.0.0
 synopsis:            An implementation of the Jinja2 template language in Haskell
 description:         Ginger is Jinja, minus the most blatant pythonisms. Wants
                      to be feature complete, but isn't quite there yet.
@@ -48,7 +48,7 @@
                , http-types >= 0.8 && (< 0.11 || >= 0.12)
                , mtl >= 2.2
                , parsec >= 3.0
-               , regex-tdfa >=1.2.3 && <=1.3
+               , regex-tdfa >=1.2.3 && <=1.5
                , safe >= 0.3
                , scientific >= 0.3
                , text >=1.2.3.1 && <1.3
diff --git a/src/Text/Ginger/GVal.hs b/src/Text/Ginger/GVal.hs
--- a/src/Text/Ginger/GVal.hs
+++ b/src/Text/Ginger/GVal.hs
@@ -36,6 +36,7 @@
                , not
                , fst, snd
                , Monad
+               , MonadFail
                , Functor
                )
 import qualified Prelude
@@ -822,7 +823,7 @@
     fromGVal :: GVal m -> Maybe a
     fromGVal = Prelude.either (const Nothing) Just . fromGValEither
 
-fromGValM :: (Monad m, FromGVal m a) => GVal m -> m a
+fromGValM :: (MonadFail m, FromGVal m a) => GVal m -> m a
 fromGValM = Prelude.either Prelude.fail return . fromGValEither
 
 instance FromGVal m Int where
diff --git a/src/Text/Ginger/Run/Builtins.hs b/src/Text/Ginger/Run/Builtins.hs
--- a/src/Text/Ginger/Run/Builtins.hs
+++ b/src/Text/Ginger/Run/Builtins.hs
@@ -59,7 +59,7 @@
 import Control.Monad.Writer
 import Control.Monad.Reader
 import Control.Monad.State
-import Control.Monad.Except (throwError)
+import Control.Monad.Except (throwError, MonadError)
 import Control.Applicative
 import qualified Data.HashMap.Strict as HashMap
 import Data.HashMap.Strict (HashMap)
@@ -357,13 +357,13 @@
         _ -> throwHere $ ArgumentsError (Just "split") "expected: (str, sep=null)"
 
 gfnCompose :: forall m p h. Monad m => Function (Run p m h)
-gfnCompose [] = fail "Invalid arguments to compose()"
+gfnCompose [] = throwError $ ArgumentsError (Just "compose") ""
 gfnCompose [(_, fG)] = return fG
 gfnCompose ((_, fG):xs) = do
   gG <- gfnCompose xs
   case (asFunction fG, asFunction gG) of
-    (Nothing, _) -> fail $ "Argument to compose() is not a function"
-    (_, Nothing) -> fail $ "PANIC: Composition of functions is not a function"
+    (Nothing, _) -> throwError NotAFunctionError
+    (_, Nothing) -> throwError NotAFunctionError
     (Just f, Just g) -> do
       let h args = do
               arg' <- g args
@@ -371,10 +371,10 @@
       return $ fromFunction h
 
 gfnPartial :: forall m p h. Monad m => Function (Run p m h)
-gfnPartial [] = fail "Invalid arguments to partial()"
+gfnPartial [] = throwError $ ArgumentsError (Just "partial") ""
 gfnPartial ((_, fG):args) = do
   case asFunction fG of
-    Nothing -> fail "Argument to partial() is not a function"
+    Nothing -> throwError $ ArgumentsError (Just "partial") "Argument must be a function"
     Just f -> do
       let h args' = do
             f (args ++ args')
@@ -400,7 +400,7 @@
 gfnZipWith :: forall m p h. Monad m => Function (Run p m h)
 gfnZipWith ((Nothing, gfn):args) = do
   zipFunction <- case asFunction gfn of
-    Nothing -> fail $ "Invalid args to zipwith"
+    Nothing -> throwError $ ArgumentsError (Just "zipwith") ""
     Just fn -> return fn
   toGVal <$> go zipFunction (fmap fst args) (fmap (fromMaybe [] . asList . snd) args)
   where
@@ -417,7 +417,7 @@
         return $ currentVal : tailVals
 
 
-gfnMap :: Monad m => Function m
+gfnMap :: (Monad m, MonadError (RuntimeError a) m) => Function m
 gfnMap args = do
     let parsedArgs = extractArgsDefL
             [ ("collection", def)
@@ -433,7 +433,7 @@
                    , Just (asText attribute)
                    )
         _ ->
-            fail "Invalid args to map()"
+            throwError $ ArgumentsError (Just "map") ""
     mapFunction <- case (functionMay, attributeMay) of
         (Just f, _) -> return f
         (Nothing, Just key) -> return $ \case
@@ -441,7 +441,7 @@
                 return $ lookupLooseDef def (toGVal key) item
             _ ->
                 return def
-        _ -> fail "You have to pass a function or an attribute"
+        _ -> throwError $ ArgumentsError (Just "map") "You have to pass a function or an attribute"
     case (dictMay, listMay) of
         (Just items, _) ->
             dict <$> forM items
