diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,14 @@
 # Revision history for Entity
 
-## 0.0.4.4 -- 2024-12-23
+## 0.0.5.1 -- 2025-04-23
+
+* Update dependencies
+
+## 0.0.5.0 -- 2024-01-19
+
+* Update version of `bytestring` to 0.12, `text` to 2.1 and `postgresql-simple` to 0.7 ([#72](https://github.com/tchoutri/pg-entity/pull/72))
+
+## 0.0.4.4 -- 2023-12-23
 * Remove extraneous quoting of table name in _selectWithFields
 
 ## 0.0.4.3 -- 2023-06-26
diff --git a/docs/book/404.html b/docs/book/404.html
--- a/docs/book/404.html
+++ b/docs/book/404.html
@@ -71,10 +71,12 @@
         <!-- Hide / unhide sidebar before it is displayed -->
         <script>
             var html = document.querySelector('html');
-            var sidebar = 'hidden';
+            var sidebar = null;
             if (document.body.clientWidth >= 1080) {
                 try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                 sidebar = sidebar || 'visible';
+            } else {
+                sidebar = 'hidden';
             }
             html.classList.remove('sidebar-visible');
             html.classList.add("sidebar-" + sidebar);
@@ -87,11 +89,33 @@
             <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
         </nav>
 
+        <!-- Track and set sidebar scroll position -->
+        <script>
+            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
+            sidebarScrollbox.addEventListener('click', function(e) {
+                if (e.target.tagName === 'A') {
+                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
+                }
+            }, { passive: true });
+            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
+            sessionStorage.removeItem('sidebar-scroll');
+            if (sidebarScrollTop) {
+                // preserve sidebar scroll position when navigating via links within sidebar
+                sidebarScrollbox.scrollTop = sidebarScrollTop;
+            } else {
+                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
+                var activeSection = document.querySelector('#sidebar .active');
+                if (activeSection) {
+                    activeSection.scrollIntoView({ block: 'center' });
+                }
+            }
+        </script>
+
         <div id="page-wrapper" class="page-wrapper">
 
             <div class="page">
                                 <div id="menu-bar-hover-placeholder"></div>
-                <div id="menu-bar" class="menu-bar sticky bordered">
+                <div id="menu-bar" class="menu-bar sticky">
                     <div class="left-buttons">
                         <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                             <i class="fa fa-bars"></i>
@@ -166,22 +190,6 @@
 
         </div>
 
-        <!-- Livereload script (if served using the cli tool) -->
-        <script>
-            const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
-            const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
-            const socket = new WebSocket(wsAddress);
-            socket.onmessage = function (event) {
-                if (event.data === "reload") {
-                    socket.close();
-                    location.reload();
-                }
-            };
-
-            window.onbeforeunload = function() {
-                socket.close();
-            }
-        </script>
 
 
 
diff --git a/docs/book/ErrorsGuide.html b/docs/book/ErrorsGuide.html
--- a/docs/book/ErrorsGuide.html
+++ b/docs/book/ErrorsGuide.html
@@ -70,10 +70,12 @@
         <!-- Hide / unhide sidebar before it is displayed -->
         <script>
             var html = document.querySelector('html');
-            var sidebar = 'hidden';
+            var sidebar = null;
             if (document.body.clientWidth >= 1080) {
                 try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                 sidebar = sidebar || 'visible';
+            } else {
+                sidebar = 'hidden';
             }
             html.classList.remove('sidebar-visible');
             html.classList.add("sidebar-" + sidebar);
@@ -86,11 +88,33 @@
             <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
         </nav>
 
+        <!-- Track and set sidebar scroll position -->
+        <script>
+            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
+            sidebarScrollbox.addEventListener('click', function(e) {
+                if (e.target.tagName === 'A') {
+                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
+                }
+            }, { passive: true });
+            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
+            sessionStorage.removeItem('sidebar-scroll');
+            if (sidebarScrollTop) {
+                // preserve sidebar scroll position when navigating via links within sidebar
+                sidebarScrollbox.scrollTop = sidebarScrollTop;
+            } else {
+                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
+                var activeSection = document.querySelector('#sidebar .active');
+                if (activeSection) {
+                    activeSection.scrollIntoView({ block: 'center' });
+                }
+            }
+        </script>
+
         <div id="page-wrapper" class="page-wrapper">
 
             <div class="page">
                                 <div id="menu-bar-hover-placeholder"></div>
-                <div id="menu-bar" class="menu-bar sticky bordered">
+                <div id="menu-bar" class="menu-bar sticky">
                     <div class="left-buttons">
                         <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                             <i class="fa fa-bars"></i>
@@ -241,22 +265,6 @@
 
         </div>
 
-        <!-- Livereload script (if served using the cli tool) -->
-        <script>
-            const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
-            const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
-            const socket = new WebSocket(wsAddress);
-            socket.onmessage = function (event) {
-                if (event.data === "reload") {
-                    socket.close();
-                    location.reload();
-                }
-            };
-
-            window.onbeforeunload = function() {
-                socket.close();
-            }
-        </script>
 
 
 
diff --git a/docs/book/Introduction.html b/docs/book/Introduction.html
--- a/docs/book/Introduction.html
+++ b/docs/book/Introduction.html
@@ -70,10 +70,12 @@
         <!-- Hide / unhide sidebar before it is displayed -->
         <script>
             var html = document.querySelector('html');
-            var sidebar = 'hidden';
+            var sidebar = null;
             if (document.body.clientWidth >= 1080) {
                 try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                 sidebar = sidebar || 'visible';
+            } else {
+                sidebar = 'hidden';
             }
             html.classList.remove('sidebar-visible');
             html.classList.add("sidebar-" + sidebar);
@@ -86,11 +88,33 @@
             <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
         </nav>
 
+        <!-- Track and set sidebar scroll position -->
+        <script>
+            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
+            sidebarScrollbox.addEventListener('click', function(e) {
+                if (e.target.tagName === 'A') {
+                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
+                }
+            }, { passive: true });
+            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
+            sessionStorage.removeItem('sidebar-scroll');
+            if (sidebarScrollTop) {
+                // preserve sidebar scroll position when navigating via links within sidebar
+                sidebarScrollbox.scrollTop = sidebarScrollTop;
+            } else {
+                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
+                var activeSection = document.querySelector('#sidebar .active');
+                if (activeSection) {
+                    activeSection.scrollIntoView({ block: 'center' });
+                }
+            }
+        </script>
+
         <div id="page-wrapper" class="page-wrapper">
 
             <div class="page">
                                 <div id="menu-bar-hover-placeholder"></div>
-                <div id="menu-bar" class="menu-bar sticky bordered">
+                <div id="menu-bar" class="menu-bar sticky">
                     <div class="left-buttons">
                         <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                             <i class="fa fa-bars"></i>
@@ -192,22 +216,6 @@
 
         </div>
 
-        <!-- Livereload script (if served using the cli tool) -->
-        <script>
-            const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
-            const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
-            const socket = new WebSocket(wsAddress);
-            socket.onmessage = function (event) {
-                if (event.data === "reload") {
-                    socket.close();
-                    location.reload();
-                }
-            };
-
-            window.onbeforeunload = function() {
-                socket.close();
-            }
-        </script>
 
 
 
diff --git a/docs/book/Tutorial.html b/docs/book/Tutorial.html
--- a/docs/book/Tutorial.html
+++ b/docs/book/Tutorial.html
@@ -70,10 +70,12 @@
         <!-- Hide / unhide sidebar before it is displayed -->
         <script>
             var html = document.querySelector('html');
-            var sidebar = 'hidden';
+            var sidebar = null;
             if (document.body.clientWidth >= 1080) {
                 try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                 sidebar = sidebar || 'visible';
+            } else {
+                sidebar = 'hidden';
             }
             html.classList.remove('sidebar-visible');
             html.classList.add("sidebar-" + sidebar);
@@ -86,11 +88,33 @@
             <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
         </nav>
 
+        <!-- Track and set sidebar scroll position -->
+        <script>
+            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
+            sidebarScrollbox.addEventListener('click', function(e) {
+                if (e.target.tagName === 'A') {
+                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
+                }
+            }, { passive: true });
+            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
+            sessionStorage.removeItem('sidebar-scroll');
+            if (sidebarScrollTop) {
+                // preserve sidebar scroll position when navigating via links within sidebar
+                sidebarScrollbox.scrollTop = sidebarScrollTop;
+            } else {
+                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
+                var activeSection = document.querySelector('#sidebar .active');
+                if (activeSection) {
+                    activeSection.scrollIntoView({ block: 'center' });
+                }
+            }
+        </script>
+
         <div id="page-wrapper" class="page-wrapper">
 
             <div class="page">
                                 <div id="menu-bar-hover-placeholder"></div>
-                <div id="menu-bar" class="menu-bar sticky bordered">
+                <div id="menu-bar" class="menu-bar sticky">
                     <div class="left-buttons">
                         <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                             <i class="fa fa-bars"></i>
@@ -368,22 +392,6 @@
 
         </div>
 
-        <!-- Livereload script (if served using the cli tool) -->
-        <script>
-            const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
-            const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
-            const socket = new WebSocket(wsAddress);
-            socket.onmessage = function (event) {
-                if (event.data === "reload") {
-                    socket.close();
-                    location.reload();
-                }
-            };
-
-            window.onbeforeunload = function() {
-                socket.close();
-            }
-        </script>
 
 
 
diff --git a/docs/book/book.js b/docs/book/book.js
--- a/docs/book/book.js
+++ b/docs/book/book.js
@@ -68,7 +68,7 @@
     }
 
     // updates the visibility of play button based on `no_run` class and
-    // used crates vs ones available on http://play.rust-lang.org
+    // used crates vs ones available on https://play.rust-lang.org
     function update_play_button(pre_block, playground_crates) {
         var play_button = pre_block.querySelector(".play-button");
 
@@ -179,7 +179,7 @@
     // even if highlighting doesn't apply
     code_nodes.forEach(function (block) { block.classList.add('hljs'); });
 
-    Array.from(document.querySelectorAll("code.language-rust")).forEach(function (block) {
+    Array.from(document.querySelectorAll("code.hljs")).forEach(function (block) {
 
         var lines = Array.from(block.querySelectorAll('.boring'));
         // If no lines were hidden, return
@@ -346,7 +346,7 @@
         }
 
         setTimeout(function () {
-            themeColorMetaTag.content = getComputedStyle(document.body).backgroundColor;
+            themeColorMetaTag.content = getComputedStyle(document.documentElement).backgroundColor;
         }, 1);
 
         if (window.ace && window.editors) {
@@ -551,13 +551,6 @@
             firstContact = null;
         }
     }, { passive: true });
-
-    // Scroll sidebar to current active section
-    var activeSection = document.getElementById("sidebar").querySelector(".active");
-    if (activeSection) {
-        // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
-        activeSection.scrollIntoView({ block: 'center' });
-    }
 })();
 
 (function chapterNavigation() {
@@ -676,13 +669,14 @@
         }, { passive: true });
     })();
     (function controllBorder() {
-        menu.classList.remove('bordered');
-        document.addEventListener('scroll', function () {
+        function updateBorder() {
             if (menu.offsetTop === 0) {
                 menu.classList.remove('bordered');
             } else {
                 menu.classList.add('bordered');
             }
-        }, { passive: true });
+        }
+        updateBorder();
+        document.addEventListener('scroll', updateBorder, { passive: true });
     })();
 })();
diff --git a/docs/book/css/chrome.css b/docs/book/css/chrome.css
--- a/docs/book/css/chrome.css
+++ b/docs/book/css/chrome.css
@@ -22,7 +22,7 @@
         the screen on small screens. Without it, dragging on mobile Safari
         will want to reposition the viewport in a weird way.
     */
-    overflow-x: hidden;
+    overflow-x: clip;
 }
 
 /* Menu Bar */
diff --git a/docs/book/css/general.css b/docs/book/css/general.css
--- a/docs/book/css/general.css
+++ b/docs/book/css/general.css
@@ -5,6 +5,7 @@
 :root {
     /* Browser default font-size is 16px, this way 1 rem = 10px */
     font-size: 62.5%;
+    color-scheme: var(--color-scheme);
 }
 
 html {
diff --git a/docs/book/css/print.css b/docs/book/css/print.css
--- a/docs/book/css/print.css
+++ b/docs/book/css/print.css
@@ -22,14 +22,6 @@
     overflow-y: initial;
 }
 
-code {
-    background-color: #666666;
-    border-radius: 5px;
-
-    /* Force background to be printed in Chrome */
-    -webkit-print-color-adjust: exact;
-}
-
 pre > .buttons {
     z-index: 2;
 }
diff --git a/docs/book/css/variables.css b/docs/book/css/variables.css
--- a/docs/book/css/variables.css
+++ b/docs/book/css/variables.css
@@ -50,6 +50,8 @@
     --searchresults-border-color: #888;
     --searchresults-li-bg: #252932;
     --search-mark-bg: #e3b171;
+
+    --color-scheme: dark;
 }
 
 .coal {
@@ -90,6 +92,8 @@
     --searchresults-border-color: #98a3ad;
     --searchresults-li-bg: #2b2b2f;
     --search-mark-bg: #355c7d;
+
+    --color-scheme: dark;
 }
 
 .light {
@@ -130,6 +134,8 @@
     --searchresults-border-color: #888;
     --searchresults-li-bg: #e4f2fe;
     --search-mark-bg: #a2cff5;
+
+    --color-scheme: light;
 }
 
 .navy {
@@ -170,6 +176,8 @@
     --searchresults-border-color: #5c5c68;
     --searchresults-li-bg: #242430;
     --search-mark-bg: #a2cff5;
+
+    --color-scheme: dark;
 }
 
 .rust {
@@ -210,6 +218,8 @@
     --searchresults-border-color: #888;
     --searchresults-li-bg: #dec2a2;
     --search-mark-bg: #e69f67;
+
+    --color-scheme: light;
 }
 
 @media (prefers-color-scheme: dark) {
diff --git a/docs/book/index.html b/docs/book/index.html
--- a/docs/book/index.html
+++ b/docs/book/index.html
@@ -70,10 +70,12 @@
         <!-- Hide / unhide sidebar before it is displayed -->
         <script>
             var html = document.querySelector('html');
-            var sidebar = 'hidden';
+            var sidebar = null;
             if (document.body.clientWidth >= 1080) {
                 try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                 sidebar = sidebar || 'visible';
+            } else {
+                sidebar = 'hidden';
             }
             html.classList.remove('sidebar-visible');
             html.classList.add("sidebar-" + sidebar);
@@ -86,11 +88,33 @@
             <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
         </nav>
 
+        <!-- Track and set sidebar scroll position -->
+        <script>
+            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
+            sidebarScrollbox.addEventListener('click', function(e) {
+                if (e.target.tagName === 'A') {
+                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
+                }
+            }, { passive: true });
+            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
+            sessionStorage.removeItem('sidebar-scroll');
+            if (sidebarScrollTop) {
+                // preserve sidebar scroll position when navigating via links within sidebar
+                sidebarScrollbox.scrollTop = sidebarScrollTop;
+            } else {
+                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
+                var activeSection = document.querySelector('#sidebar .active');
+                if (activeSection) {
+                    activeSection.scrollIntoView({ block: 'center' });
+                }
+            }
+        </script>
+
         <div id="page-wrapper" class="page-wrapper">
 
             <div class="page">
                                 <div id="menu-bar-hover-placeholder"></div>
-                <div id="menu-bar" class="menu-bar sticky bordered">
+                <div id="menu-bar" class="menu-bar sticky">
                     <div class="left-buttons">
                         <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                             <i class="fa fa-bars"></i>
@@ -192,22 +216,6 @@
 
         </div>
 
-        <!-- Livereload script (if served using the cli tool) -->
-        <script>
-            const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
-            const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
-            const socket = new WebSocket(wsAddress);
-            socket.onmessage = function (event) {
-                if (event.data === "reload") {
-                    socket.close();
-                    location.reload();
-                }
-            };
-
-            window.onbeforeunload = function() {
-                socket.close();
-            }
-        </script>
 
 
 
diff --git a/docs/book/print.html b/docs/book/print.html
--- a/docs/book/print.html
+++ b/docs/book/print.html
@@ -71,10 +71,12 @@
         <!-- Hide / unhide sidebar before it is displayed -->
         <script>
             var html = document.querySelector('html');
-            var sidebar = 'hidden';
+            var sidebar = null;
             if (document.body.clientWidth >= 1080) {
                 try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                 sidebar = sidebar || 'visible';
+            } else {
+                sidebar = 'hidden';
             }
             html.classList.remove('sidebar-visible');
             html.classList.add("sidebar-" + sidebar);
@@ -87,11 +89,33 @@
             <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
         </nav>
 
+        <!-- Track and set sidebar scroll position -->
+        <script>
+            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
+            sidebarScrollbox.addEventListener('click', function(e) {
+                if (e.target.tagName === 'A') {
+                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
+                }
+            }, { passive: true });
+            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
+            sessionStorage.removeItem('sidebar-scroll');
+            if (sidebarScrollTop) {
+                // preserve sidebar scroll position when navigating via links within sidebar
+                sidebarScrollbox.scrollTop = sidebarScrollTop;
+            } else {
+                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
+                var activeSection = document.querySelector('#sidebar .active');
+                if (activeSection) {
+                    activeSection.scrollIntoView({ block: 'center' });
+                }
+            }
+        </script>
+
         <div id="page-wrapper" class="page-wrapper">
 
             <div class="page">
                                 <div id="menu-bar-hover-placeholder"></div>
-                <div id="menu-bar" class="menu-bar sticky bordered">
+                <div id="menu-bar" class="menu-bar sticky">
                     <div class="left-buttons">
                         <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                             <i class="fa fa-bars"></i>
@@ -452,22 +476,6 @@
 
         </div>
 
-        <!-- Livereload script (if served using the cli tool) -->
-        <script>
-            const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
-            const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
-            const socket = new WebSocket(wsAddress);
-            socket.onmessage = function (event) {
-                if (event.data === "reload") {
-                    socket.close();
-                    location.reload();
-                }
-            };
-
-            window.onbeforeunload = function() {
-                socket.close();
-            }
-        </script>
 
 
 
diff --git a/docs/book/tomorrow-night.css b/docs/book/tomorrow-night.css
--- a/docs/book/tomorrow-night.css
+++ b/docs/book/tomorrow-night.css
@@ -1,7 +1,7 @@
 /* Tomorrow Night Theme */
-/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
+/* https://github.com/jmblog/color-themes-for-highlightjs */
 /* Original theme - https://github.com/chriskempson/tomorrow-theme */
-/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
+/* https://github.com/jmblog/color-themes-for-highlightjs */
 
 /* Tomorrow Comment */
 .hljs-comment {
diff --git a/docs/src/Tutorial.hs b/docs/src/Tutorial.hs
--- a/docs/src/Tutorial.hs
+++ b/docs/src/Tutorial.hs
@@ -28,7 +28,7 @@
 import Database.PostgreSQL.Transact (DBT)
 import GHC.Generics
 
-import Control.Monad.Error
+import Control.Monad.IO.Class (MonadIO (..))
 import qualified Data.Time as Time
 import qualified Data.UUID.V4 as UUID
 import Database.PostgreSQL.Entity
diff --git a/pg-entity.cabal b/pg-entity.cabal
--- a/pg-entity.cabal
+++ b/pg-entity.cabal
@@ -5,7 +5,7 @@
   A PostgreSQL layer to safely expand your SQL queries with a lightweight eDSL.
   Read the tutorial at https://hackage.haskell.org/package/pg-entity/src/docs/book/index.html
 
-version:            0.0.4.4
+version:            0.0.5.1
 homepage:
   https://hackage.haskell.org/package/pg-entity/src/docs/book/index.html
 
@@ -15,9 +15,7 @@
 category:           Database
 license:            MIT
 build-type:         Simple
-tested-with:
-  GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.8
-
+tested-with:        GHC ==9.2.8 || ==9.4.8 || ==9.6.7 || ==9.8.4 || ==9.10.1
 extra-source-files:
   CHANGELOG.md
   LICENSE.md
@@ -105,18 +103,17 @@
   hs-source-dirs:  src
   build-depends:
     , base               >=4.12     && <5.0
-    , bytestring         ^>=0.11
+    , bytestring         ^>=0.12
     , colourista         ^>=0.1
     , parsec             ^>=3.1
     , pg-transact        ^>=0.3
-    , postgresql-simple  ^>=0.6
+    , postgresql-simple  ^>=0.7
     , resource-pool      ^>=0.4
-    , template-haskell   >=2.15.0.0 && <2.22.0.0.0
-    , text               ^>=2.0
-    , text-display       ^>=0.0
+    , template-haskell   >=2.15.0.0 && <2.23.0.0.0
+    , text               ^>=2.1
+    , text-display       ^>=1.0
     , text-manipulate    ^>=0.3
-    , time               ^>=1.12
-    , uuid               ^>=1.3
+    , time               ^>=1.14
     , vector             ^>=0.13
 
   if flag(prod)
diff --git a/src/Database/PostgreSQL/Entity.hs b/src/Database/PostgreSQL/Entity.hs
--- a/src/Database/PostgreSQL/Entity.hs
+++ b/src/Database/PostgreSQL/Entity.hs
@@ -98,18 +98,47 @@
 import Database.PostgreSQL.Entity.Types
 
 {- $setup
- >>> :set -XQuasiQuotes
- >>> :set -XOverloadedStrings
- >>> :set -XOverloadedLists
- >>> :set -XTypeApplications
- >>> import Database.PostgreSQL.Entity
- >>> import Database.PostgreSQL.Entity.Types
- >>> import Database.PostgreSQL.Entity.Internal
- >>> import Database.PostgreSQL.Entity.Internal.BlogPost
- >>> import Database.PostgreSQL.Entity.Internal.QQ
- >>> import Database.PostgreSQL.Simple.Types (Query (..))
- >>> import Data.Vector (Vector)
- >>> import qualified Data.Vector as V
+>>> :set -XQuasiQuotes
+>>> :set -XOverloadedStrings
+>>> :set -XOverloadedLists
+>>> :set -XTypeApplications
+>>> import Database.PostgreSQL.Entity
+>>> import Database.PostgreSQL.Entity.Types
+>>> import Database.PostgreSQL.Entity.Internal
+>>> import Database.PostgreSQL.Entity.Internal.QQ
+>>> import Database.PostgreSQL.Simple.Types (Query (..))
+>>> import Data.Vector (Vector)
+>>> import qualified Data.Vector as V
+>>> import Data.Time (UTCTime)
+>>> import GHC.Generics (Generic)
+>>> :{
+>>> data Author = Author
+>>>   { authorId :: Int
+>>>   , name :: Text
+>>>   , createdAt :: UTCTime
+>>>   }
+>>>   deriving stock (Eq, Generic, Ord, Show)
+>>>   deriving anyclass (FromRow, ToRow)
+>>>   deriving
+>>>     (Entity)
+>>>     via (GenericEntity '[PrimaryKey "author_id", TableName "authors"] Author)
+>>>
+>>> data BlogPost = BlogPost
+>>>   { blogPostId :: Int
+>>>   -- ^ Primary key
+>>>   , authorId :: Int
+>>>   -- ^ Foreign keys, for which we need an explicit type annotation
+>>>   , intList :: Vector Int
+>>>   , title :: Text
+>>>   , content :: Text
+>>>   , createdAt :: UTCTime
+>>>   }
+>>>   deriving stock (Eq, Generic, Ord, Show)
+>>>   deriving anyclass (FromRow, ToRow)
+>>>   deriving
+>>>     (Entity)
+>>>     via (GenericEntity '[PrimaryKey "blog_post_id", TableName "blogposts"] BlogPost)
+>>> :}
 -}
 
 {- $highlevel
@@ -348,7 +377,7 @@
  __Examples__
 
  >>> _select @BlogPost
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\""
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\""
 
  @since 0.0.1.0
 -}
@@ -359,8 +388,8 @@
 
  __Examples__
 
- >>> _selectWithFields @BlogPost [ [field| blogpost_id |], [field| created_at |] ]
- "SELECT \"blogposts\".\"blogpost_id\", \"blogposts\".\"created_at\" FROM \"\"blogposts\"\""
+ >>> _selectWithFields @BlogPost [ [field| blog_post_id |], [field| created_at |] ]
+ "SELECT \"blogposts\".\"blog_post_id\", \"blogposts\".\"created_at\" FROM \"blogposts\""
 
  @since 0.0.1.0
 -}
@@ -379,11 +408,11 @@
 
  __Examples__
 
- >>> _select @BlogPost <> _where [[field| blogpost_id |]]
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"blogpost_id\" = ?"
+ >>> _select @BlogPost <> _where [[field| blog_post_id |]]
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"blog_post_id\" = ?"
 
- >>> _select @BlogPost <> _where [ [field| uuid_list |] ]
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"uuid_list\" = ?"
+ >>> _select @BlogPost <> _where [ [field| int_list |] ]
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"int_list\" = ?"
 
  @since 0.0.1.0
 -}
@@ -397,10 +426,10 @@
  __Examples__
 
  >>> _selectWhere @BlogPost [ [field| author_id |] ]
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ?"
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ?"
 
  >>> _selectWhere @BlogPost [ [field| author_id |], [field| title |]]
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ? AND \"title\" = ?"
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ? AND \"title\" = ?"
 
  @since 0.0.1.0
 -}
@@ -411,7 +440,7 @@
  r
 
  >>> _selectWhereNotNull @BlogPost [ [field| author_id |] ]
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NOT NULL"
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NOT NULL"
 
  @since 0.0.1.0
 -}
@@ -421,7 +450,7 @@
 {-| Produce a SELECT statement where the provided fields are checked for being null.
 
  >>> _selectWhereNull @BlogPost [ [field| author_id |] ]
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NULL"
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NULL"
 
  @since 0.0.1.0
 -}
@@ -431,7 +460,7 @@
 {-| Produce a SELECT statement where the given field is checked aginst the provided array of values .
 
  >>> _selectWhereIn @BlogPost [field| title |] [ "Unnamed", "Mordred's Song" ]
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"title\" IN ('Unnamed', 'Mordred''s Song')"
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"title\" IN ('Unnamed', 'Mordred''s Song')"
 
  @since 0.0.2.0
 -}
@@ -443,7 +472,7 @@
  __Examples__
 
  >>> _joinSelect @BlogPost @Author
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\", authors.\"author_id\", authors.\"name\", authors.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" USING(author_id)"
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\", authors.\"author_id\", authors.\"name\", authors.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" USING(author_id)"
 
  @since 0.0.1.0
 -}
@@ -510,7 +539,7 @@
  __Examples__
 
  >>> _joinSelectOneByField @BlogPost @Author [field| author_id |] [field| name |] :: Query
- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" ON \"blogposts\".\"author_id\" = \"authors\".\"author_id\" WHERE authors.\"name\" = ?"
+ "SELECT blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" ON \"blogposts\".\"author_id\" = \"authors\".\"author_id\" WHERE authors.\"name\" = ?"
 
  @since 0.0.2.0
 -}
@@ -544,7 +573,7 @@
  __Examples__
 
  >>> _insert @BlogPost
- "INSERT INTO \"blogposts\" (\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?)"
+ "INSERT INTO \"blogposts\" (\"blog_post_id\", \"author_id\", \"int_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?)"
 
  @since 0.0.1.0
 -}
@@ -558,14 +587,14 @@
 
  __Examples__
 
- >>> _onConflictDoUpdate [[field| blogpost_id |]] [ [field| title |], [field| content |]]
- " ON CONFLICT (blogpost_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content"
+ >>> _onConflictDoUpdate [[field| blog_post_id |]] [ [field| title |], [field| content |]]
+ " ON CONFLICT (blog_post_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content"
 
- >>> _onConflictDoUpdate [[field| blogpost_id |], [field| author_id |]] [ [field| title |], [field| content |]]
- " ON CONFLICT (blogpost_id, author_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content"
+ >>> _onConflictDoUpdate [[field| blog_post_id |], [field| author_id |]] [ [field| title |], [field| content |]]
+ " ON CONFLICT (blog_post_id, author_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content"
 
- >>> _insert @BlogPost <> _onConflictDoUpdate [[field| blogpost_id |]] [ [field| title |], [field| content |]]
- "INSERT INTO \"blogposts\" (\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT (blogpost_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content"
+ >>> _insert @BlogPost <> _onConflictDoUpdate [[field| blog_post_id |]] [ [field| title |], [field| content |]]
+ "INSERT INTO \"blogposts\" (\"blog_post_id\", \"author_id\", \"int_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT (blog_post_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content"
 
  @since 0.0.2.0
 -}
@@ -586,7 +615,7 @@
  "UPDATE \"authors\" SET (\"name\", \"created_at\") = ROW(?, ?) WHERE \"author_id\" = ?"
 
  >>> _update @BlogPost
- "UPDATE \"blogposts\" SET (\"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") = ROW(?, ?, ?, ?, ?) WHERE \"blogpost_id\" = ?"
+ "UPDATE \"blogposts\" SET (\"author_id\", \"int_list\", \"title\", \"content\", \"created_at\") = ROW(?, ?, ?, ?, ?) WHERE \"blog_post_id\" = ?"
 
  @since 0.0.1.0
 -}
@@ -655,7 +684,7 @@
  __Examples__
 
  >>> _delete @BlogPost
- "DELETE FROM \"blogposts\" WHERE \"blogpost_id\" = ?"
+ "DELETE FROM \"blogposts\" WHERE \"blog_post_id\" = ?"
 
  @since 0.0.1.0
 -}
diff --git a/src/Database/PostgreSQL/Entity/Internal.hs b/src/Database/PostgreSQL/Entity/Internal.hs
--- a/src/Database/PostgreSQL/Entity/Internal.hs
+++ b/src/Database/PostgreSQL/Entity/Internal.hs
@@ -53,14 +53,63 @@
 import Database.PostgreSQL.Entity.Types
 
 {- $setup
- >>> :set -XQuasiQuotes
- >>> :set -XOverloadedLists
- >>> :set -XTypeApplications
- >>> import Database.PostgreSQL.Entity
- >>> import Database.PostgreSQL.Entity.Types
- >>> import Database.PostgreSQL.Entity.Internal.BlogPost
- >>> import Database.PostgreSQL.Entity.Internal.QQ
- >>> import Database.PostgreSQL.Entity.Internal.Unsafe
+>>> :set -XQuasiQuotes
+>>> :set -XOverloadedStrings
+>>> :set -XOverloadedLists
+>>> :set -XTypeApplications
+>>> import Database.PostgreSQL.Entity
+>>> import Database.PostgreSQL.Simple.FromRow (FromRow(..))
+>>> import Database.PostgreSQL.Simple.ToRow
+>>> import Database.PostgreSQL.Entity.Types
+>>> import Database.PostgreSQL.Entity.Internal
+>>> import Database.PostgreSQL.Entity.Internal.QQ
+>>> import Database.PostgreSQL.Simple.Types (Query (..))
+>>> import Data.Vector (Vector)
+>>> import qualified Data.Vector as V
+>>> import Data.Time (UTCTime)
+>>> import GHC.Generics (Generic)
+>>> :{
+>>> data Author = Author
+>>>   { authorId :: Int
+>>>   , name :: Text
+>>>   , createdAt :: UTCTime
+>>>   }
+>>>   deriving stock (Eq, Generic, Ord, Show)
+>>>   deriving anyclass (FromRow, ToRow)
+>>>   deriving
+>>>     (Entity)
+>>>     via (GenericEntity '[PrimaryKey "author_id", TableName "authors"] Author)
+>>>
+>>> data BlogPost = BlogPost
+>>>   { blogPostId :: Int
+>>>   -- ^ Primary key
+>>>   , authorId :: Int
+>>>   -- ^ Foreign keys, for which we need an explicit type annotation
+>>>   , intList :: Vector Int
+>>>   , title :: Text
+>>>   , content :: Text
+>>>   , createdAt :: UTCTime
+>>>   }
+>>>   deriving stock (Eq, Generic, Ord, Show)
+>>>   deriving anyclass (FromRow, ToRow)
+>>>   deriving
+>>>     (Entity)
+>>>     via (GenericEntity '[PrimaryKey "blog_post_id", TableName "blogposts"] BlogPost)
+>>>
+>>> data Tags = Tags
+>>>   { category :: Text
+>>>   , labels :: [Text]
+>>>   }
+>>>
+>>> instance Entity Tags where
+>>>   tableName = "tags"
+>>>   schema = Just "public"
+>>>   primaryKey = [field| category |]
+>>>   fields =
+>>>     [ [field| category |]
+>>>     , [field| labels |]
+>>>     ]
+>>> :}
 -}
 
 {-| Wrap the given text between parentheses
@@ -147,7 +196,7 @@
  __Examples__
 
  >>> expandFields @BlogPost
- "\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\""
+ "\"blog_post_id\", \"author_id\", \"int_list\", \"title\", \"content\", \"created_at\""
 
  @since 0.0.1.0
 -}
@@ -159,7 +208,7 @@
  __Examples__
 
  >>> expandQualifiedFields @BlogPost
- "blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\""
+ "blogposts.\"blog_post_id\", blogposts.\"author_id\", blogposts.\"int_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\""
 
  @since 0.0.1.0
 -}
@@ -173,7 +222,7 @@
  __Examples__
 
  >>> expandQualifiedFields' (fields @BlogPost) "legacy"
- "legacy.\"blogpost_id\", legacy.\"author_id\", legacy.\"uuid_list\", legacy.\"title\", legacy.\"content\", legacy.\"created_at\""
+ "legacy.\"blog_post_id\", legacy.\"author_id\", legacy.\"int_list\", legacy.\"title\", legacy.\"content\", legacy.\"created_at\""
 
  @since 0.0.1.0
 -}
@@ -203,7 +252,7 @@
  __Examples__
 
  >>> qualifyFields "legacy" (fields @BlogPost)
- [Field "legacy.\"blogpost_id\"" Nothing,Field "legacy.\"author_id\"" Nothing,Field "legacy.\"uuid_list\"" Nothing,Field "legacy.\"title\"" Nothing,Field "legacy.\"content\"" Nothing,Field "legacy.\"created_at\"" Nothing]
+ [Field "legacy.\"blog_post_id\"" Nothing,Field "legacy.\"author_id\"" Nothing,Field "legacy.\"int_list\"" Nothing,Field "legacy.\"title\"" Nothing,Field "legacy.\"content\"" Nothing,Field "legacy.\"created_at\"" Nothing]
 
  @since 0.0.1.0
 -}
@@ -221,7 +270,7 @@
  "\"ids\" = ?"
 
  >>> fmap placeholder $ fields @BlogPost
- ["\"blogpost_id\" = ?","\"author_id\" = ?","\"uuid_list\" = ?","\"title\" = ?","\"content\" = ?","\"created_at\" = ?"]
+ ["\"blog_post_id\" = ?","\"author_id\" = ?","\"int_list\" = ?","\"title\" = ?","\"content\" = ?","\"created_at\" = ?"]
 
  @since 0.0.1.0
 -}
@@ -293,13 +342,20 @@
     fieldNames = fmap fieldName fs'
     process f = quoteName f <> " IS NULL"
 
+{-| Produce an "IS (<value1>, <value2>, …, <valueN>)" clause
+
+>>> isIn [field| colour |] [ "yellow", "blue", "magenta" ]
+"\"colour\" IN ('yellow', 'blue', 'magenta')"
+
+@since 0.0.2.0
+-}
 isIn :: Field -> Vector Text -> Text
 isIn f values = process f <> " IN (" <> fold (intercalateVector ", " vals) <> ")"
   where
     vals = fmap literal values
     process f' = quoteName $ fieldName f'
 
-{-| Since the 'Query' type has an 'IsString' instance, the process of converting from 'Text' to 'String' to 'Query' is
+{-| Since the 'Query' type has an 'Data.String.IsString' instance, the process of converting from 'Text' to 'String' to 'Query' is
  factored into this function
 
  ⚠ This may be dangerous and an unregulated usage of this function may expose to you SQL injection attacks
diff --git a/src/Database/PostgreSQL/Entity/Internal/QQ.hs b/src/Database/PostgreSQL/Entity/Internal/QQ.hs
--- a/src/Database/PostgreSQL/Entity/Internal/QQ.hs
+++ b/src/Database/PostgreSQL/Entity/Internal/QQ.hs
@@ -27,8 +27,8 @@
 
  > instance Entity BlogPost where
  >   tableName  = "blogposts"
- >   primaryKey = [field| blogpost_id |]
- >   fields = [ [field| blogpost_id |]
+ >   primaryKey = [field| blog_post_id |]
+ >   fields = [ [field| blog_post_id |]
  >            , [field| author_id |]
  >            , [field| uuid_list :: uuid[] |] -- ← This is where we specify an optional PostgreSQL type annotation
  >            , [field| title |]
diff --git a/test/EntitySpec.hs b/test/EntitySpec.hs
--- a/test/EntitySpec.hs
+++ b/test/EntitySpec.hs
@@ -39,10 +39,12 @@
 import Database.PostgreSQL.Simple (Only (Only))
 import Database.PostgreSQL.Transact (DBT)
 
+import qualified Data.Map as Map
 import Data.Maybe (fromJust)
 import qualified Data.Set as S
 import qualified Data.Set as Set
 import Data.Vector (Vector)
+import qualified Data.Vector as Vector
 import Database.PostgreSQL.Entity.Types
 import Optics.Core
 import Test.Tasty
@@ -132,7 +134,11 @@
         _joinSelectWithFields @BlogPost @Author [[field| title |]] [[field| name |]]
           <> _where [[field| name |]]
   result <- liftDB (query Select q (Only ("Hansi Kürsch" :: Text)) :: MonadIO m => DBT m (Vector (Text, Text)))
-  U.assertEqual [("The Script for my requiem", "Hansi Kürsch"), ("Mordred's Song", "Hansi Kürsch")] result
+  let actualMap = Map.fromList $ Vector.toList result
+  let expectedMap = Map.fromList [("The Script for my requiem", "Hansi Kürsch"), ("Mordred's Song", "Hansi Kürsch")]
+  U.assertEqual
+    expectedMap
+    actualMap
 
 changeAuthorName :: TestM ()
 changeAuthorName = do
diff --git a/test/Utils.hs b/test/Utils.hs
--- a/test/Utils.hs
+++ b/test/Utils.hs
@@ -4,6 +4,7 @@
 module Utils where
 
 import Control.Exception.Safe
+import Control.Monad (void)
 import Control.Monad.IO.Class
 import Control.Monad.Reader
 import Data.ByteString (ByteString)
