diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Revision history for type-of-html
 
+## 1.6.2.0  -- 2021-02-06
+
+* simplifications
+* performance improvements
+* ghc 9 compatibility
+
 ## 1.6.1.0  -- 2020-11-07
 
 * visual fixes
diff --git a/bench/Alloc.hs b/bench/Alloc.hs
--- a/bench/Alloc.hs
+++ b/bench/Alloc.hs
@@ -24,37 +24,37 @@
 main :: IO ()
 main = mainWith $ do
 
-  f "()"                   id ()                                 [    144 ,   -16 ,      16 ,     0 ,      0 ]
-  f "Int"                  id (123456789 :: Int)                 [    192 ,     0 ,       0 ,     0 ,      0 ]
-  f "Word"                 id (123456789 :: Word)                [    192 ,     0 ,       0 ,     0 ,      0 ]
-  f "Char"                 id 'a'                                [    192 ,     0 ,       0 ,     0 ,      0 ]
-  f "Integer"              id (123456789 :: Integer)             [    248 ,     0 ,       0 ,     0 ,      0 ]
-  f "Proxy"                id (Proxy :: Proxy "a")               [    280 ,   -16 ,      16 ,     0 ,      0 ]
-  f "oneElement Proxy"     S.oneElement (Proxy :: Proxy "b")     [    280 ,   -16 ,      16 ,     0 ,      0 ]
-  f "oneElement ()"        S.oneElement ()                       [    280 ,   -16 ,      16 ,     0 ,      0 ]
-  f "oneAttribute ()"      (ClassA :=) ()                        [    280 ,   -16 ,      16 ,     0 ,      0 ]
-  f "oneAttribute Proxy"   (ClassA :=) (Proxy :: Proxy "c")      [    280 ,   -16 ,      16 ,     0 ,      0 ]
-  f "listElement"          S.listElement ()                      [    608 ,     0 ,       0 ,     0 ,      0 ]
-  f "Double"               id (123456789 :: Double)              [    360 ,     0 ,       0 ,     0 ,    -32 ]
-  f "oneElement"           S.oneElement ""                       [    368 ,     0 ,       0 ,     0 ,      0 ]
-  f "nestedElement"        S.nestedElement ""                    [    368 ,     0 ,       0 ,     0 ,      0 ]
-  f "listOfAttributes"     (\x -> [ClassA := x, ClassA := x]) () [    744 ,     0 ,       0 ,     0 ,      0 ]
-  f "Float"                id (123456789 :: Float)               [    400 ,     0 ,       0 ,     0 ,    -72 ]
-  f "oneAttribute"         (ClassA :=) ""                        [    480 ,     0 ,       0 ,     0 ,      0 ]
-  f "parallelElement"      S.parallelElement ""                  [    520 ,     0 ,       0 ,   -16 ,      0 ]
-  f "parallelAttribute"    (\x -> ClassA := x # IdA := x) ""     [    672 ,     0 ,       0 ,   -16 ,      0 ]
-  f "elementWithAttribute" (\x -> Div :@ (ClassA := x) :> x) ""  [    656 ,     0 ,       0 ,     0 ,      0 ]
-  f "listOfListOf"         (\x -> Div :> [I :> [Span :> x]]) ()  [   1200 ,     0 ,      64 ,     0 ,      0 ]
-  f "helloWorld"           M.helloWorld ()                       [   1232 ,   -16 ,      16 ,     0 ,      0 ]
-  f "page"                 M.page ()                             [   1416 ,   -16 ,    -144 ,     0 ,      0 ]
-  f "table"                M.table (2,2)                         [   2616 ,     0 ,      64 ,   -96 ,     64 ]
-  f "AttrShort"            M.attrShort ()                        [   2680 ,   -16 ,     856 ,     0 ,      0 ]
-  f "pageA"                M.pageA ()                            [   2504 ,  -176 ,      64 ,     0 ,      0 ]
-  f "AttrLong"             M.attrLong ()                         [   2680 ,   -16 ,     856 ,     0 ,      0 ]
-  f "Big table"            M.table (50,10)                       [ 120072 ,     0 ,    1600 , -8096 ,   7952 ]
-  f "hackage upload"       EX.hackageUpload ()                   [ 698784 ,   488 , -204792 , -1408 , -47120 ]
+  f "()"                   id ()                                 [    144 ,   -16 ,      16 ,      0 ,    0 ,      0 ]
+  f "Int"                  id (123456789 :: Int)                 [    192 ,     0 ,       0 ,      0 ,    0 ,      0 ]
+  f "Word"                 id (123456789 :: Word)                [    192 ,     0 ,       0 ,      0 ,    0 ,      0 ]
+  f "Char"                 id 'a'                                [    256 ,     0 ,       0 ,      0 ,    0 ,     16 ]
+  f "Integer"              id (123456789 :: Integer)             [    248 ,     0 ,       0 ,      0 ,    0 ,      0 ]
+  f "Proxy"                id (Proxy :: Proxy "a")               [    280 ,   -16 ,      16 ,      0 ,    0 ,      0 ]
+  f "oneElement Proxy"     S.oneElement (Proxy :: Proxy "b")     [    280 ,   -16 ,      16 ,      0 ,    0 ,      0 ]
+  f "oneElement ()"        S.oneElement ()                       [    280 ,   -16 ,      16 ,      0 ,    0 ,     24 ]
+  f "oneAttribute ()"      (ClassA :=) ()                        [    280 ,   -16 ,      16 ,      0 ,    0 ,     24 ]
+  f "oneAttribute Proxy"   (ClassA :=) (Proxy :: Proxy "c")      [    280 ,   -16 ,      16 ,      0 ,    0 ,      0 ]
+  f "listElement"          S.listElement ()                      [    608 ,     0 ,       0 ,      0 ,    0 ,     -8 ]
+  f "Double"               id (123456789 :: Double)              [    360 ,     0 ,       0 ,      0 ,  -32 ,    -72 ]
+  f "oneElement"           S.oneElement ""                       [    608 ,   -32 ,     -16 ,    -56 ,    0 ,     88 ]
+  f "nestedElement"        S.nestedElement ""                    [    608 ,   -32 ,     -16 ,    -56 ,    0 ,     24 ]
+  f "listOfAttributes"     (\x -> [ClassA := x, ClassA := x]) () [    744 ,     0 ,       0 ,      0 ,    0 ,      8 ]
+  f "Float"                id (123456789 :: Float)               [    400 ,     0 ,       0 ,      0 ,  -72 ,    -72 ]
+  f "oneAttribute"         (ClassA :=) ""                        [    792 ,   -32 ,     -16 ,    -56 ,    0 ,     16 ]
+  f "parallelElement"      S.parallelElement ""                  [    920 ,   -64 ,    -168 ,    -56 ,    0 ,     56 ]
+  f "parallelAttribute"    (\x -> ClassA := x # IdA := x) ""     [   1104 ,   -64 ,    -168 ,    -56 ,    0 ,     96 ]
+  f "elementWithAttribute" (\x -> Div :@ (ClassA := x) :> x) ""  [   1104 ,   -64 ,    -168 ,    -56 ,    0 ,     32 ]
+  f "listOfListOf"         (\x -> Div :> [I :> [Span :> x]]) ()  [   1200 ,     0 ,      64 ,      0 ,    0 ,    -32 ]
+  f "helloWorld"           M.helloWorld ()                       [    480 ,   -16 ,      16 ,      0 ,    0 ,    192 ]
+  f "page"                 M.page ()                             [   2616 ,  -176 ,    -984 ,      0 ,    0 ,    104 ]
+  f "table"                M.table (2,2)                         [   2616 ,     0 ,      64 ,    -96 ,   64 ,   -120 ]
+  f "AttrShort"            M.attrShort ()                        [   5560 ,  -400 ,   -2360 ,      0 ,    0 ,   2688 ]
+  f "pageA"                M.pageA ()                            [   5864 ,  -624 ,   -2704 ,      0 ,    0 ,    632 ]
+  f "AttrLong"             M.attrLong ()                         [   5560 ,  -400 ,   -2360 ,      0 ,    0 ,   2736 ]
+  f "Big table"            M.table (50,10)                       [ 120072 ,     0 ,    1600 ,  -8096 , 7952 , -15288 ]
+  f "hackage upload"       EX.hackageUpload ()                   [ 852896 , -21952, -558368 , -12248 ,    0 ,  89336 ]
 
-  where versions =                                               [    802 ,   804 ,     806 ,   808 ,    810 ]
+  where versions =                                               [    802 ,   804 ,     806 ,    808 ,  810 ,    900 ]
 
         ghc = fromInteger . sum . take (length $ takeWhile (<= (__GLASGOW_HASKELL__ :: Int)) versions)
 
diff --git a/bench/Perf.hs b/bench/Perf.hs
--- a/bench/Perf.hs
+++ b/bench/Perf.hs
@@ -3,8 +3,6 @@
 {-# LANGUAGE TypeApplications #-}
 {-# LANGUAGE DataKinds        #-}
 
-{-# LANGUAGE CPP #-}
-
 module Main where
 
 import Html
@@ -15,6 +13,7 @@
 import qualified Medium            as M
 import qualified ExampleTypeOfHtml as ET
 
+import Data.Word
 import Criterion.Main
 import Data.String
 import System.Random
@@ -23,123 +22,121 @@
 import Text.Blaze.Html.Renderer.Utf8
 import qualified Data.Text.Lazy   as LT
 import qualified Data.Text        as T
-
-#if __GLASGOW_HASKELL__ <= 802
-import Data.Semigroup ((<>))
-#endif
+import Data.ByteString.Lazy (foldl1')
 
 main :: IO ()
 main = defaultMain
   [ small
-  , medium
+  , string
   , comparison
   , scaling
   ]
 
 small :: Benchmark
 small = bgroup "Small"
-  [ bench "oneElement"                   $ nf (renderByteString . S.oneElement) ""
-  , bench "nestedElement"                $ nf (renderByteString . S.nestedElement) ""
-  , bench "parallelElement"              $ nf (renderByteString . S.parallelElement) ""
-  , bench "listElement"                  $ nf (renderByteString . S.listElement) ""
-  , bench "Int"                          $ nf renderByteString (123456789 :: Int)
-  , bench "Integer"                      $ nf renderByteString (123456789 :: Integer)
-  , bench "Double"                       $ nf renderByteString (123456789 :: Double)
-  , bench "Float"                        $ nf renderByteString (123456789 :: Float)
-  , bench "Word"                         $ nf renderByteString (123456789 :: Word)
-  , bench "Proxy"                        $ nf renderByteString (Proxy :: Proxy "abc")
-  , bench "Char"                         $ nf renderByteString 'a'
-  , bench "oneElement Proxy"             $ nf (renderByteString . S.oneElement) (Proxy :: Proxy "abc")
-  , bench "()"                           $ nf renderByteString ()
-  , bench "oneElement ()"                $ nf (renderByteString . S.oneElement) ()
-  , bench "oneAttribute"                 $ nf (renderByteString . (ClassA :=)) ""
-  , bench "oneAttribute ()"              $ nf (renderByteString . (ClassA :=))  ()
-  , bench "oneAttribute Proxy"           $ nf (renderByteString . (ClassA :=))  (Proxy :: Proxy "abc")
-  , bench "parallelAttribute"            $ nf (\x -> renderByteString $ ClassA := x # IdA := x) ""
-  , bench "elementWithAttribute"         $ nf (\x -> renderByteString $ Div :@ (ClassA := x) :> x) ""
-  , bench "elementWithParallelAttribute" $ nf (\x -> renderByteString $ Div :@ (ClassA := x # IdA := x) :> x) ""
-  , bench "listOfAttributes"             $ nf (\x -> renderByteString [ClassA := x, ClassA := x]) ""
-  , bench "listOfListOf"                 $ nf (\x -> renderByteString $ Div :> [I :> [Span :> x]]) ""
+  [ bench "oneElement"                   $ nf (run . S.oneElement) ""
+  , bench "nestedElement"                $ nf (run . S.nestedElement) ""
+  , bench "parallelElement"              $ nf (run . S.parallelElement) ""
+  , bench "listElement"                  $ nf (run . S.listElement) ""
+  , bench "Int"                          $ nf run (123456789 :: Int)
+  , bench "Integer"                      $ nf run (123456789 :: Integer)
+  , bench "Double"                       $ nf run (123456789 :: Double)
+  , bench "Float"                        $ nf run (123456789 :: Float)
+  , bench "Word"                         $ nf run (123456789 :: Word)
+  , bench "Proxy"                        $ nf run (Proxy :: Proxy "abc")
+  , bench "Char"                         $ nf run 'a'
+  , bench "oneElement Proxy"             $ nf (run . S.oneElement) (Proxy :: Proxy "abc")
+  , bench "()"                           $ nf run ()
+  , bench "oneElement ()"                $ nf (run . S.oneElement) ()
+  , bench "oneAttribute"                 $ nf (run . (ClassA :=)) ""
+  , bench "oneAttribute ()"              $ nf (run . (ClassA :=))  ()
+  , bench "oneAttribute Proxy"           $ nf (run . (ClassA :=))  (Proxy :: Proxy "abc")
+  , bench "parallelAttribute"            $ nf (\x -> run $ ClassA := x # IdA := x) ""
+  , bench "elementWithAttribute"         $ nf (\x -> run $ Div :@ (ClassA := x) :> x) ""
+  , bench "elementWithParallelAttribute" $ nf (\x -> run $ Div :@ (ClassA := x # IdA := x) :> x) ""
+  , bench "listOfAttributes"             $ nf (\x -> run [ClassA := x, ClassA := x]) ""
+  , bench "listOfListOf"                 $ nf (\x -> run $ Div :> [I :> [Span :> x]]) ""
   ]
 
-medium :: Benchmark
-medium = bgroup "Medium"
-  [ bench "helloWorld"          $ nf (renderByteString . M.helloWorld) "medium"
-  , bench "randomString"        $ nf renderByteString randomString
-  , bench "randomStringRaw"     $ nf renderByteString randomStringRaw
-  , bench "randomStrictText"    $ nf renderByteString randomStrictText
-  , bench "randomStrictTextRaw" $ nf renderByteString randomStrictTextRaw
-  , bench "randomLazyText"      $ nf renderByteString randomLazyText
-  , bench "randomLazyTextRaw"   $ nf renderByteString randomLazyTextRaw
-  , bench "page"                $ nf (renderByteString . M.page) "medium"
-  , bench "pageA"               $ nf (renderByteString . M.pageA) "medium"
-  , bench "attrShort"           $ nf (renderByteString . M.attrShort) "medium"
-  , bench "attrLong"            $ nf (renderByteString . M.attrLong) "medium"
-  ]
+string :: Benchmark
+string = bgroup "String"
+  [ bench "randomString"        $ nf (run . (# randomString)) (1::Int)
+  , bench "randomStringRaw"     $ nf (run . (# randomStringRaw)) (1::Int)
+  , bench "randomTextStrict"    $ nf (run . (# randomTextStrict)) (1::Int)
+  , bench "randomTextStrictRaw" $ nf (run . (# randomTextStrictRaw)) (1::Int)
+  , bench "randomTextLazy"      $ nf (run . (# randomTextLazy)) (1::Int)
+  , bench "randomTextLazyRaw"   $ nf (run . (# randomTextLazyRaw)) (1::Int)
+  , bench "literalString"       $ nf (run . (# "ASCII: aeiou {v{H5@!(c@i/e^93q7+.8?u)c:F?&_*jQ:{s-G[MIO*!.F$%dXDROgf3{Sts6zR)RT\\RM#5^~3/uKGCb2i,\\EXMN;hb0CJ/?9s4KHet-Fr-kV9H~T<RLpzQ9IV3OJexSv*QFk !%Ebyg4[$0{~-{{SS7nn(!D@LbOi-)Etz'z@H+s]VJ!'a>_:UJ7^zxZt=1*JdEF%U wPzEb!$GN7v.b?k99^(il6*a!Z/$bbHhv.8sor lm1j\\i\\;BBlD|sOSwm,f9hrc3rtpR454Lmqi0!'Xfk>L>;*%a(.W+tT)4f/yOHR_.Vscl3DIkeNs8s84B4WfzL&1^oiL6|Iv{4)v7&j_Y2)KYGp_\"`e#B{.TYqFyrXinq1*/=JTquF,*_pY`tdoi2~(?bZqS?i$5fSVmIE6/FW/F=^`5=.=v#\"]+{lw/(VUvY$'kOld,M'rKQY\\fO}+G|n-!X\\5@8L0C|hUMj5/8Mq`Rzg#j;VCmd}[+*wPb>{$?1e|0xZ\"'u?YWx7\"]>,gK^GgJ_F5ea1@e'{ K37nSU[h8_[K<kvAKA2+_&O}Jh-pxQqxS{78ZS9EBp_54vnjs@~>raHm)R> @Rht{je~,^7'9m8*O;2}x'{Z/B5l$~+jV.br@tFrFf?C1,[1fkjPzK?f.GP4 y-d)=#n'+99B0$V^^flg`AA9YlQ4t<gZ(8]JKyJz9OE$&oTY*?[N!Xf?d.Xm5\\-lC/!h$dqmh%{6\")B=oh/$4vQp3mvu`}rg] lwtyF5@nik&Tqn{}I_@$E!fa*8PmOGU6i06s,}NbW!8bH+gm1Zd,~du@>:Om.',9D2:c%i~YXNyJ2cQg=SVb34~c).1@U7'?_*JMkZWMpgO)&P(_QMAyolbwb%+Ep!?j;tcjEat>g>u97tfQ bNU#A783O1=K@)C;BW 4XlHor4}alsfCW[!3<=;(9fIeBE=AHd,`k!<V3-`fyP`3[4\"2 d,o(b<dZ4uMPY'bW8DT<T0&jFFg5dJ?hs23NLqBf+0RAfrj&RW3t]FI[xQh8L^6fYS&w`'N\"iSYTG%MR\"g9Li6]GK.<yiRX)NZXvbj\\-!if=@{J=\\T;GsE#(*/qy3v-7b]EYNScTsO:wH9vq0aybQuF+}H&],pp(S8tmh;\"^Q*&+ea`[45Zz'Wfn4-Ot=&;LmHfcta^b`@2xxg^B~k./o:ox-!(O:hmynqMhrJN~Fl82>q94D8d^|v^B?(O;G*b|Zt_#!pdM[qD8Ki>fnNzRGY*;1oI{><!``Lj8Y@\\%G%|!v KU)!.7U@kM!kdE>?Kad4b6XUq^MmF=r+P\\VuP78*-stkdnA%;ogs\"2d&#+fu8F9BXE(h%o,aoy$oufM\"(CGaO+lZqEuQ{`LL#b}Cog|y^N{WL*'1`KXHBS&13#ZEdvHE?:${N/wM ^}m40qaX6Qt_+aOu~6L,La rHkaEu\\%tDYLGHj3\\Yso7o\\rx%,_F^znD*}*mv9I$$\"}jg2ZP#f ,;*9|\\xi^{|;2)KtbM=U?Zr_:gI$OoXngAQ4ec.>d7>~1.W{OI.Rn*cMO4 3 CLR>h%c:C`\"J{0tX,V9f2!b;nIjP3;!(\\?G.dV`uI8!\">N;yoN9@;IVFg@w{l.h7K{zbQn^,=v[_%y[IdO3If#gGZ/WtDsAus!3>RymX>D-G7^hI~wj!'@w`CFN88Z_2p1NKC@iW-UB8S9kk.EWgTrWJe=s{g`:[{kn<J,I_C}ti.y5]0|qnfGjTCLK moKExUlh]kiM\">.bRIn^gM1y,u#RA|VOO,Ay39<voplYY:AR'_ovZ%6~@aI<AJt1Ms+/qd)]Mo9Te 8$k>tB&YkxopGc*tQT`y*\"rv\"!3l<lY.=j/%P>\"rsHfYkaMBZ+%HJ-'sl( |Puq\\dM{H% Wr:\">b1<|}7c#+Q]L,>*WU2(%~SBGiS6u[yB2iaYmV23b&c0BFbn\"c1/Gf;`1\\uKGw\\,tj#fsx+73*am~^>f/GwQ75-\"/]C*|e`ys}]]XfdZcg0>AseXE:*B5&.)^9@:$j0f;eeN6,j7{Q|K'6O<L6+}?eE,Dziy5I#b4xUKn0P[1(xkxG_Nf6(Qv$.B\";iDT_WYzcx1zrkSQAcAjG9Z:4(.|`uH5@r$8 h&gf wr!}.f\\/I4h-&~-lm`cBhaD8z9d!Sn|l}!wM].;5Lb<)<gNGcc-J.)3l=oJtQ/,>n-#\"Rav0a=LTUX9mIkH?Y$^a}U|LwOGa}3w3q7iB.cs}:up/*)#Fny34()\"ebt!]J7K,nZ8tOC,48\\gs;P]H+qWHWm\\LCy'6$pNLM}^haz&H(z[[EIXrBxHYD`5i17 )>$oDK\\xe:OEny6B}F`%7CR|k4G\\I?r~s(o:?\"(}s4{VT9+id@N:bzFC E[&%N}2G+VMbv}XC[BZ[kJ]V=gL-Ph](TVe,vpzaK7B0+K|c<:n0mSm3.:2U,j4cwZP1U1d{:5SWf(f[NXXM~7-_bk%oK{O@I|5U)o<zjE#Yy4~\\>n,\"-mC!uLF*`Pw\\vIOS7XJ.h~]t^^9CY#3H-1]g6s,_g_RyU-9TqccG3V)aa_}0IinfD6|?2+vQyRj_Q<s\\nh33^P+\"{RPOBr.?R4?(=dFKHP4bc6yfrgRQs*NyY(v;&UAgN`Z!yq\"4R940ksl[-WA]nk|4TPz1N|5bFhWC-q!+D.='B]d$3|w^)[_dB%((W!t=ToZ{0\\GP'&R^s*~0`28r)7Mkx@NfJ#cUGS9J|,rPFTj> mWIAJBzw(/,OSB?xD&b}S}?? yX1!PDYWd.%!k@(:=hJZ%{.|;-ENBE>t$Z!,cr3J6:Rs;;.[}(OA$C(dh;?\"iC- \\ J?:+RBEdHQ`nj>.sS#4zXMwbSQRlNXAjz9C#:w~Yk&iYh)ZZz{RC99~6HWJFl:lFLxbgb=z,+l$P \\|Ak8UGx]64h.V_ Eg*cR9)D`G7{r5~XJ:lk0K'#~bIam9w'L'-l(xP`tz:9*3f/ROz9EM=MW2Yd~q!\\'47]3p]KR@.nniZ8l,{5HU>EUQxRX(V n:EcL_h<u<YU-D5C~c?<>Lj#3V;yl*2czy~b ch}_[2,|j9D|HJS%em-=;'h;hqF$eDH]h<fh|s$_!r5{HRQu#g{q;xb?Q3s?!4:+K(EEds:p(idYI+a<.1'{7M!`$B],i-3p;w}~8lWkFL#\"~MVP/_R?yIoTarf 9vqgvH%$ArC)e'.(DAcbwG/'W|BQIO}|?Dc^QE%ukdj~[z]okuGXzP!IBT>DbtxgRjM=Je08AV9y-~gZ $KN_o=&@$qwE]^?D_'I5t3\"yS:_$\"'sC 9!Wvzh?58Ax5h `DQO/\\bG`t2!7_Fj#%qC%5+cA9-m9Xu*$`M4gJ\",5#*1:i=|]{i'pf:[hOTH7l#H~lKQfDjK/NyFV:ZM+HJ{W\\[4S!*lFP5-@sMsJW%,`'!J4[Jcs0WG/&|0)CBugj4fr,$-.<$NV,aGX4 @XrKga!`t@H.9x1PQ:9e^m8e3CiTT/wR^vEB+]?yGw.so(%>ZaGNn|@`ffeI>HoPBO&2L'3FMyI\"'BdObllKr8]D\\t(S&>`VXo2G.H#E`T'M3GQ3+6f:h^Na^5tBA1BV<]$]-K;ENy)\"7Y-4a|K57oeTE^b%.zkG[87vD 6#^[8*%SrSbg%;5*M{?s|vV{8\\)TPKZq']-j^wMQsu.-]_[r*<+hzZ@v:M::z3CqM]prE!8!e7D~-N>&#6,FLb~ lA3GAC:\"oE}?m4hq'nfJ.=BQL#dyl/Qhw2bmgWt=JX_]FM3rSgJ2Hg`3?41R%\"\"iN[MD;O4-xX8B3L,F+9g! iEZ[3(97qQ/(pGZzY:BY8$ps#E`j}Trl~lyIrj{`'VDraHaMN-Y]%V\\U:tQ*m1W)V}|''-8wIBQ(01u|5_,.ZE3g@m9\";q_AbOa7TvelHS/|(tfJBm1KBBct+c}<#S}`?p>0)b^p)]4E\\*j3I`?L_~Oqhmh#*:,meS)Z<{~'~1],51n itIBtO+enEm}nH35ckS?^*hzv\"(~`AA|i\\emYgM!N40Ll@=)8AL[j<FM7+o|:e)**;w]XEE_3#,:on%_K,!TQ25ucrWoz_[Hs>:)^wkN?Qw+Fw,{aGORlUn`%g%)\",PW.y@#w`\"H,e#D^9WeGOP3: r:X(Tq35[as%\\r6{lC1$cx9NX\"FhjS -1ZksJrkoBFZbK4P^@~wm`RZ/@&i?~lv[1=A[Y!VlcfC(m=jL\"/=.aTkv{ W=s:xEcKO/^LA@o'[`C^*Iga/<'Rs\\:O!-&,xpZ-tPZY0H'rb*Ja\\.Ok2jl)$::\\|p#|9;goJ<'^7E^t(W~S@dKIg_KwlP:\" 7l|s$-hP^Hit<s~e6GGCF3:L<+-fEKmqS5eQ=,.Y\"@&PYtP>~Dzr,'zh.2A& 8,<Jx*2Zg(Ox_Myg[?0\"6V<,U~:(\"Rr{/^*&AFs2UMyL:gE(V,.8.@U*e8V5&E6fcfZL%=&b^3fE8\\+#r<fC'&0E)9'A`}3!O{TONVI:BP{3;3W:9z6b<4g=42jhPS>]}Xb!p#GS[^#F}gFPxm|5pfjj=t?FYU37#ABC4`S@[UU0*r|_F`!1;QL@K,>G53t_S\"Y{f;#4*&wnJ%V-$+P7Az}k8Fqw=cxH!R^h]w:Ydgn<12h$Hvx!qV#&`{*@\\5yFdi\\HYX$*ij2R5MU_ExkuqG1}}T&66zrFC@R#%]ml{\"j&^&V[kq56A3-.4>G6( @7-\"7Q3lDm),lvL2P|b5$$+#L&fcWfwNv9Wwn4}S'j%urMWceqOmZ&sO)Id}wY&Ak#t-ut^Ci^wnR5eS6ez4{P|k/TjrdK@|7KF$9~Q)Eso@C2m(*&2sf[J4 Pl`uzm3CfZ=XRP0L&FhPDC#$aP`~teiQ6A8p/mOIBN{2J!0e4qrLSUpvRl<2-AK($Lwa%e2)xBhZ9Lt[fL%7\"Vp~$[WA=,?:2Jb3h$uwvPA4V&b{tTVS rhdI\\c][:ba&o\\;2YSNg gz,8@/.Kvsjp+OI6zgInKS~vh,*F]v3v.4~:m;i#5E8aYc]J)B:`K.N[;Zo>hGoF>S29G4/+oQ/i>OXxn^%i$O}|SI\\!'z@wSKCe2]Fj$[L\\YDDvs{}|%i uou6i]\\n5=Y+==FJIpjBi42[|*x(IZ.Qt8(w^qD+&<f^Wkk:f7:_G$a:<B,]*W3SsoD&)ze&h;rf<Iy6&ECGVN'?0Nskh q HG=|}zNEshQtp6b41HP+]M((62(f1eB\\Ug)Qs-K].\"`g}Lj#h|4D`L*q$*OcD3)(HD60(f3h?ie=t]7(L8@^];H[To%n|uT''Xkf~Ls{y<0Z\\O(rq9Vgr_%,O*GL}eDb:Q/zB$6%RX#1_uLo:o#F)G@H|*Zu!{B..zC$7qSwhR!&OeR[4o&V88VB]_QZp0:8sBsz+12OQrr`wqKv6GM>1RS#/E998/gc]L.{2/$#$D+:J4x.}WEK3l c|-=>g`q*Y%P..8j%XYpl&n`8,^/?d$m`*0$\\BY_u#pW7f\"9;bvibvZYd$dT++K1tI*TmF{7B=b&N\"{SV:^U2\\h\"7+Ky_p&,2K!hk;61]X<l-o4$=,NuI*G!T_OXI((('QIW:}7uGoU6,U!{QQPi[9z$aKv~.=ZS9m4-NJrReG6h1*^'E?]v83=3$cS(>C!BFb4f(\\XkOCcHSJ<)It5dI+2r~8-eLY20&<\"~`v,uPq3\"Z8$1^B{%R*o$X4$$G^j\"I/*O.&`n)j,53#axtjx\\S%+12,##~L7[|wH?^%uUR}Ow&U/.&iy)#I|KD:\"K[!z:d1$;>~_5,[b?s?$^qen;O|4vf/P<:aShNx#S:^VS5sikFU>~ BObjd+\\j`(@0SQs`,a-*E`!GtxOe'n 0t[OL>'s`3^~[fCUY<_|IaEasw:wD5FV9R'0X43Y}]RDjl,&aq#6i|s_`g=PM^V9yk$@Fvy?MN\\9wdtYt#.kqR2G8i?ND;LqMU?d'L3~]#x{KT\\rNkl7;_ceL}{B-~6$jt}~ZTP/RwwI\\`l6dVN{D1 tkc|8!ATe$@ohoX)z*<ZK~]S2R`F&:0hUn3L<P8l0 M?j\"UubIn.1=b$eogi~I,ydIh4wnw|5y,bQD?Y(:Cx2a?bfi<2h'd*$@!/{A,VFM&]b''j(7r.tc%`F+|LN4B2dUx/)of[HP.(hV%K-g&;nwwG 3'RRAEK\"81[F5@JCd{D`T~&YeS-m8m?j0n)Cb@*HO_&)i<O+U=QQ0<}T|3QO&ReY/gxkto8Jzf%w^'l/4,z,Vykd@ I@IS{ tH7t,7p(OJpZ-DPPFM{5[ngaFk/^~'IE_mlR%ayA*?f HjD5/.XD&+rr/lK*1m;^ObyB+hjl d$23m*i\\6Pu[:4ZG\"- ~8GrGRd>$nM]U0tiahQo7^`pR},\\9.2Vt00Op.hhL+o}@h{aKg+1LDhyG5$n[0sxwFzH;%{&^5O`Z)LozW.Lu<n/rz$1@9| ~t*?L~HHx9:]<BAEV]u/Kb^/=&H?nfUyCa1y&A7xaAJ%E(C=xEB%l<'4GMbq`i_!'WUR~++ ln/u'h9 kzw\"Q's?z7*{p2=iHz\\JoK^jA=TGVe~NY3nl[T)'0`2W^7hEnds8N$$g?qgig]VV`nI#)g!Ck?7\"S3\"-HjHre:\"2cX}pH1u@tk^c=Bm`?6#cOhbD/&R[Z*X)$hal+M@\"$ hj;GN;e8),CQV0 `=itZYz\\2oY5EFE@T.~4L}uoo%%:|;/4A59p0&W--zA}~@*4<6af\\6fY7 h8^jeYc\\em=C4'[dl.eMcy;eiAmD]GH\\I~h&R`?<%L)I+%R@\\eyvQu&0zyh3&M_7`&o%)Y^7TqN!BiHTR*pT`&{RR@Nub4yd=FG\\a5=e$HNO_(WB#?@kak S'ubUEw1vL~!VaMxa~r?sG)\\A Y3W.s*=/Mf.R'8:.&cTX=('qzE-{?->Vy/l`Dt}Cfz,+[vu\\~z.\"Z!8tqKmW4eRZfFiyw[@'X?Um(w A:iR?bL]eK%lp=|{K0]qdn,B:t)e]yEDwn!/Xsw:6w0hwK2iH|e&sy$61eja8cWQ~?UN..p|xA3Jm`~j9(w#&#Qv5*5Cbt$N2hF!]EKLE~iePo$,I5hf,/n<cL0\"gP!J\\sRL~+ 3[?Zl,AGd0ZOCDL0O_+vLcAJS^$ IxpR>v-8e{\\Rhza],.AtQY@oB,,E5.VIWh#@k`0v6}WB~A|6tLzG\\A.V:cOcGy-d2XBj4OUN;?7}mj{Cl*]bs8+#PKbU$?+qp=jcguw%BGC`}'orA:*&Cxnaf'3AI{7cLzE@SCrBYskD!2wDENR13zb>xQO/:k+[i<Xt}<Yunq{z3(Qk!\\a]J\"QB5m;]31nojJ4XT|z{|(&a*H}Qw0\"9rMv+#<TvXf{\"5fk+!rRAL9B)`s#3$FY&& m|o4AT;ROjnjzq\"Y/y<9\\nc3A,_Y\"40p\\{K[MY==g`SjhNv8b<C 6`WvY\\ssYd_2Q] a9D`35gH*2\\2/|JxC4&kLp\\~G97V)G\\C+i-mzz\\vW}xv~xYnad%q(Q?H0\\b?9xUz-'%yC>(MX%4t]\"~j0E$+=AD(o:e\" nj30,aD#7Y#M b JImD~&?vkq5mL@J1s]].y=FNjC-m$L9K/Jp6Y[Y2uU((\\8K$2]8X-[(m? (g!X3iQPv7Qj&+:D=[ ?WZ}X)<R/ttr Wu-Pe+5fRwRA@)Q@S:b}WAi}=d=yqfuNiP%o36f1Wjas5+BE0;50_K37czEEodwS2Y>+L-M&%>I'k>k88FBn^kJ\\`7}3W5w~(zI(JXrO=lO#j%/2<jrO=x!|TN|qH!:NElrXM5C(/#7,q!AIlru[<*qgOs>4(TN\"]rMrMUGo%r?diYRhytsvp#Ec^,Yu-tN3c`$IEU^LI ,\"ca}I3/~E)LZkq</E0hFBLUTg9$6uG8^QT3#wO+w }:MP[W9cpF%.IF*Kv~Bp0)i&u&j4Z`~FN*pwWI=75_-$b]B:X`XPvjCXrP_qK*'-vXg,w a1)qm4u-])D@IuJV7:yryo'ql+uMI{3<3IW3CH\\UGJnsW;5]U8ZZ<9e>8,Pf7WGdYk/]K:WqU`8pk)%iL:=q[MFE)\\roWx<<=(JQB(NP=,%1P4ghND:bvk0Q>TL_%sm_ZN';W1&%(>-X*e#UT/^;,A$dsYP&XD6'^$hd>x-,o:M9.WfnA/js,*z2-80$N* $O*$Nm@Wky6H{VG'wVa[IP(]K5pfbxsy.w83Wg^~>_Ynr+:JEUU^rMm xy0nL,bgc|Qsj\\\\&[a{kY@'{Fzp'BM\\,#3Lm^pT&@ad].},efGo'jHH\\zYFM~&#+/5bH={1zjemX5wsJ$R|JiED l^(]r]4?_{H%e[D`~6^Dy^BnCDn>?WuF&RbsLVc{/E-ulm,CL+(i*AnlM4UQ%-L![j[y))uE!=$2hc[/25L8rWCGh/{,#3Ot[X:eOv\"JP'\\+m3h!&{7BJ>U^x09&g};]@j,1i2y>j&ly6+NB~%0JtC#)$^-?jV$ #gJjo(*[J_$=M1O`*~M`^jmgHi-iHw5BJ}m5f=]Ilc/WaVAO\"<]}%P!,0*N?8\\R[ZFkuL`A;%YsCNs^3/y48k65_@(iB|nW2)84f)+=up,3l(yvp|)GYli_EI*+j}=r`!M}[4v6uEG9|Q \\uB.U^@_<G+qjn\"z(gmd7L?=*TT;^=& O_kBGV=&8(udEpd-^D`]xXM?_I6I01+{a$bt--EAe5_mGo|rk/}+)I\"k\\7uGDYN*xb{!\\P.}q)NQ}!J\"_^$xnDy-RDtfoq8o}lT:=1di k%&OD1lj0Ig;uQ0rKM!on#QXur,(V>?C;-hi/l,]v<zxxI[SHZd S!+LL3]7IhxoL,u.|wgocv=8b8 %`?3^0MU9)5>-w{d^e*,}1k\\'%b9}6zv0k*ct2P]im:pq^q<5]6g)OU)@`JmA<2ot70=+p+0L4+Yfxs2`6Y$kTZgr?af2xq|0r4z6U'(MZY61\"|%veDF&M36UWv!,jx?4$jp,f%V VTO*0wy+33s-41&<!y5,.!\"5C*,}^3qNk:Q7&SXNBfzAEZbW\"m>8wzMvX(/OD^2W^sNfmlM{IRZk0F@.>3iNg_aXK#d[.`N|83@B'b4*N`k=[5e{ZF\"G`Mt#?N\\kmI14DNI \\b4dO>(.B]\\S*bM4}qS?.BjF^Mrm:VE4A-N^c'w)YvMs/;!ccv\"MC\\lfMQu`Yf*a[8*@9A}a/HuE J`Es{{N  22euv&P'$=`)x\\,vaV!a8*RR.^q/R_x> r:_z>j-y&;'r\\U&T?D(xKns%7MIE~6I$3r)u!+OWwmNRJy)bk^S.1>2UxyBK #VG&hX69/Do+Xx'.RHp1RH$i}_I%|]o;iGMuS'^DZgZ\\a.N9a?(U G_@)voP5\\y<*kyxE5o?-G>p,Gbe6n 9-n~)y\"zTF)@kR'|GRb7mj_m#%p-kEewK3DZIqJ(|&c2R{\"T=t'&B<ur&mzlF &?VV-#. b5^/*Ve9kVbN(w-]%jM~ Y|Xh?4?9jVq9S!Q;f-~J%MH>3!Nci!6`mTH^'pXxyLH.VnVeJE}4n3/\"xEc/K?m1wbCpR 1SIeMpA>m`sVSfJBjqH<[ZOB;z6~t\"DH}nY1N*;-FS$&~?Hu_:ayFm]XHKV,H\"<^R&=Vh;LE)!0/G.Up'/Oz+jNwiRo\"c&x']mi\\D\"OC3KF)wKz;|3POvt%9!q9&c!1?bnnhm?8#Z)JR$d'r]?'!mV0n8Yk,o8U'G%UR>W7@aPn-f|9UXL5tPe}3NSs!C.jC0Y!u]O5@@;w).Kt8n%5L ';,}i}9>)_{ K<0T~P+m7|Lp%!v]4jIi]!7[bZsg=&Q~7Qb/{0# MMn-acT!L$$Ra+q#p9uI0blW{pE^XRYZ.V}j9v:4b|@9JJe|~<&vurWNDt-|moga{TzzZQiD|1\"b{TaY[|x((305cwRE\\`k9I\\}%P}Zs\\|D bhdcN'Gi}*7Zg_,v%Q]Q*!?DbG0cK^G(e|&.iTmsrFvT#_ek(.!;k]vqJ$\\242& I8Z~FE5~k3Hwz8-Mj(B,YUcHcB6)U;HMTvA)aq 80WyT_n8/N/NQnv+9#j\\Ta\\*FlSk3{suX^SZ*vn h1u5]ubT>MtI`f5kH,&Q9eWD\\6\"p. kc;j|yjm'p81E*:|d)>W5;URa.~yWg+\"%)TZ|>)cv\"|*]IVg|fFstUh")) (1::Int)
+  , bench "literalStringUtf8"   $ nf (run . (# "UTF8:  äeiöü {v{H5@!(c@i/e^93q7+.8?u)c:F?&_*jQ:{s-G[MIO*!.F$%dXDROgf3{Sts6zR)RT\\RM#5^~3/uKGCb2i,\\EXMN;hb0CJ/?9s4KHet-Fr-kV9H~T<RLpzQ9IV3OJexSv*QFk !%Ebyg4[$0{~-{{SS7nn(!D@LbOi-)Etz'z@H+s]VJ!'a>_:UJ7^zxZt=1*JdEF%U wPzEb!$GN7v.b?k99^(il6*a!Z/$bbHhv.8sor lm1j\\i\\;BBlD|sOSwm,f9hrc3rtpR454Lmqi0!'Xfk>L>;*%a(.W+tT)4f/yOHR_.Vscl3DIkeNs8s84B4WfzL&1^oiL6|Iv{4)v7&j_Y2)KYGp_\"`e#B{.TYqFyrXinq1*/=JTquF,*_pY`tdoi2~(?bZqS?i$5fSVmIE6/FW/F=^`5=.=v#\"]+{lw/(VUvY$'kOld,M'rKQY\\fO}+G|n-!X\\5@8L0C|hUMj5/8Mq`Rzg#j;VCmd}[+*wPb>{$?1e|0xZ\"'u?YWx7\"]>,gK^GgJ_F5ea1@e'{ K37nSU[h8_[K<kvAKA2+_&O}Jh-pxQqxS{78ZS9EBp_54vnjs@~>raHm)R> @Rht{je~,^7'9m8*O;2}x'{Z/B5l$~+jV.br@tFrFf?C1,[1fkjPzK?f.GP4 y-d)=#n'+99B0$V^^flg`AA9YlQ4t<gZ(8]JKyJz9OE$&oTY*?[N!Xf?d.Xm5\\-lC/!h$dqmh%{6\")B=oh/$4vQp3mvu`}rg] lwtyF5@nik&Tqn{}I_@$E!fa*8PmOGU6i06s,}NbW!8bH+gm1Zd,~du@>:Om.',9D2:c%i~YXNyJ2cQg=SVb34~c).1@U7'?_*JMkZWMpgO)&P(_QMAyolbwb%+Ep!?j;tcjEat>g>u97tfQ bNU#A783O1=K@)C;BW 4XlHor4}alsfCW[!3<=;(9fIeBE=AHd,`k!<V3-`fyP`3[4\"2 d,o(b<dZ4uMPY'bW8DT<T0&jFFg5dJ?hs23NLqBf+0RAfrj&RW3t]FI[xQh8L^6fYS&w`'N\"iSYTG%MR\"g9Li6]GK.<yiRX)NZXvbj\\-!if=@{J=\\T;GsE#(*/qy3v-7b]EYNScTsO:wH9vq0aybQuF+}H&],pp(S8tmh;\"^Q*&+ea`[45Zz'Wfn4-Ot=&;LmHfcta^b`@2xxg^B~k./o:ox-!(O:hmynqMhrJN~Fl82>q94D8d^|v^B?(O;G*b|Zt_#!pdM[qD8Ki>fnNzRGY*;1oI{><!``Lj8Y@\\%G%|!v KU)!.7U@kM!kdE>?Kad4b6XUq^MmF=r+P\\VuP78*-stkdnA%;ogs\"2d&#+fu8F9BXE(h%o,aoy$oufM\"(CGaO+lZqEuQ{`LL#b}Cog|y^N{WL*'1`KXHBS&13#ZEdvHE?:${N/wM ^}m40qaX6Qt_+aOu~6L,La rHkaEu\\%tDYLGHj3\\Yso7o\\rx%,_F^znD*}*mv9I$$\"}jg2ZP#f ,;*9|\\xi^{|;2)KtbM=U?Zr_:gI$OoXngAQ4ec.>d7>~1.W{OI.Rn*cMO4 3 CLR>h%c:C`\"J{0tX,V9f2!b;nIjP3;!(\\?G.dV`uI8!\">N;yoN9@;IVFg@w{l.h7K{zbQn^,=v[_%y[IdO3If#gGZ/WtDsAus!3>RymX>D-G7^hI~wj!'@w`CFN88Z_2p1NKC@iW-UB8S9kk.EWgTrWJe=s{g`:[{kn<J,I_C}ti.y5]0|qnfGjTCLK moKExUlh]kiM\">.bRIn^gM1y,u#RA|VOO,Ay39<voplYY:AR'_ovZ%6~@aI<AJt1Ms+/qd)]Mo9Te 8$k>tB&YkxopGc*tQT`y*\"rv\"!3l<lY.=j/%P>\"rsHfYkaMBZ+%HJ-'sl( |Puq\\dM{H% Wr:\">b1<|}7c#+Q]L,>*WU2(%~SBGiS6u[yB2iaYmV23b&c0BFbn\"c1/Gf;`1\\uKGw\\,tj#fsx+73*am~^>f/GwQ75-\"/]C*|e`ys}]]XfdZcg0>AseXE:*B5&.)^9@:$j0f;eeN6,j7{Q|K'6O<L6+}?eE,Dziy5I#b4xUKn0P[1(xkxG_Nf6(Qv$.B\";iDT_WYzcx1zrkSQAcAjG9Z:4(.|`uH5@r$8 h&gf wr!}.f\\/I4h-&~-lm`cBhaD8z9d!Sn|l}!wM].;5Lb<)<gNGcc-J.)3l=oJtQ/,>n-#\"Rav0a=LTUX9mIkH?Y$^a}U|LwOGa}3w3q7iB.cs}:up/*)#Fny34()\"ebt!]J7K,nZ8tOC,48\\gs;P]H+qWHWm\\LCy'6$pNLM}^haz&H(z[[EIXrBxHYD`5i17 )>$oDK\\xe:OEny6B}F`%7CR|k4G\\I?r~s(o:?\"(}s4{VT9+id@N:bzFC E[&%N}2G+VMbv}XC[BZ[kJ]V=gL-Ph](TVe,vpzaK7B0+K|c<:n0mSm3.:2U,j4cwZP1U1d{:5SWf(f[NXXM~7-_bk%oK{O@I|5U)o<zjE#Yy4~\\>n,\"-mC!uLF*`Pw\\vIOS7XJ.h~]t^^9CY#3H-1]g6s,_g_RyU-9TqccG3V)aa_}0IinfD6|?2+vQyRj_Q<s\\nh33^P+\"{RPOBr.?R4?(=dFKHP4bc6yfrgRQs*NyY(v;&UAgN`Z!yq\"4R940ksl[-WA]nk|4TPz1N|5bFhWC-q!+D.='B]d$3|w^)[_dB%((W!t=ToZ{0\\GP'&R^s*~0`28r)7Mkx@NfJ#cUGS9J|,rPFTj> mWIAJBzw(/,OSB?xD&b}S}?? yX1!PDYWd.%!k@(:=hJZ%{.|;-ENBE>t$Z!,cr3J6:Rs;;.[}(OA$C(dh;?\"iC- \\ J?:+RBEdHQ`nj>.sS#4zXMwbSQRlNXAjz9C#:w~Yk&iYh)ZZz{RC99~6HWJFl:lFLxbgb=z,+l$P \\|Ak8UGx]64h.V_ Eg*cR9)D`G7{r5~XJ:lk0K'#~bIam9w'L'-l(xP`tz:9*3f/ROz9EM=MW2Yd~q!\\'47]3p]KR@.nniZ8l,{5HU>EUQxRX(V n:EcL_h<u<YU-D5C~c?<>Lj#3V;yl*2czy~b ch}_[2,|j9D|HJS%em-=;'h;hqF$eDH]h<fh|s$_!r5{HRQu#g{q;xb?Q3s?!4:+K(EEds:p(idYI+a<.1'{7M!`$B],i-3p;w}~8lWkFL#\"~MVP/_R?yIoTarf 9vqgvH%$ArC)e'.(DAcbwG/'W|BQIO}|?Dc^QE%ukdj~[z]okuGXzP!IBT>DbtxgRjM=Je08AV9y-~gZ $KN_o=&@$qwE]^?D_'I5t3\"yS:_$\"'sC 9!Wvzh?58Ax5h `DQO/\\bG`t2!7_Fj#%qC%5+cA9-m9Xu*$`M4gJ\",5#*1:i=|]{i'pf:[hOTH7l#H~lKQfDjK/NyFV:ZM+HJ{W\\[4S!*lFP5-@sMsJW%,`'!J4[Jcs0WG/&|0)CBugj4fr,$-.<$NV,aGX4 @XrKga!`t@H.9x1PQ:9e^m8e3CiTT/wR^vEB+]?yGw.so(%>ZaGNn|@`ffeI>HoPBO&2L'3FMyI\"'BdObllKr8]D\\t(S&>`VXo2G.H#E`T'M3GQ3+6f:h^Na^5tBA1BV<]$]-K;ENy)\"7Y-4a|K57oeTE^b%.zkG[87vD 6#^[8*%SrSbg%;5*M{?s|vV{8\\)TPKZq']-j^wMQsu.-]_[r*<+hzZ@v:M::z3CqM]prE!8!e7D~-N>&#6,FLb~ lA3GAC:\"oE}?m4hq'nfJ.=BQL#dyl/Qhw2bmgWt=JX_]FM3rSgJ2Hg`3?41R%\"\"iN[MD;O4-xX8B3L,F+9g! iEZ[3(97qQ/(pGZzY:BY8$ps#E`j}Trl~lyIrj{`'VDraHaMN-Y]%V\\U:tQ*m1W)V}|''-8wIBQ(01u|5_,.ZE3g@m9\";q_AbOa7TvelHS/|(tfJBm1KBBct+c}<#S}`?p>0)b^p)]4E\\*j3I`?L_~Oqhmh#*:,meS)Z<{~'~1],51n itIBtO+enEm}nH35ckS?^*hzv\"(~`AA|i\\emYgM!N40Ll@=)8AL[j<FM7+o|:e)**;w]XEE_3#,:on%_K,!TQ25ucrWoz_[Hs>:)^wkN?Qw+Fw,{aGORlUn`%g%)\",PW.y@#w`\"H,e#D^9WeGOP3: r:X(Tq35[as%\\r6{lC1$cx9NX\"FhjS -1ZksJrkoBFZbK4P^@~wm`RZ/@&i?~lv[1=A[Y!VlcfC(m=jL\"/=.aTkv{ W=s:xEcKO/^LA@o'[`C^*Iga/<'Rs\\:O!-&,xpZ-tPZY0H'rb*Ja\\.Ok2jl)$::\\|p#|9;goJ<'^7E^t(W~S@dKIg_KwlP:\" 7l|s$-hP^Hit<s~e6GGCF3:L<+-fEKmqS5eQ=,.Y\"@&PYtP>~Dzr,'zh.2A& 8,<Jx*2Zg(Ox_Myg[?0\"6V<,U~:(\"Rr{/^*&AFs2UMyL:gE(V,.8.@U*e8V5&E6fcfZL%=&b^3fE8\\+#r<fC'&0E)9'A`}3!O{TONVI:BP{3;3W:9z6b<4g=42jhPS>]}Xb!p#GS[^#F}gFPxm|5pfjj=t?FYU37#ABC4`S@[UU0*r|_F`!1;QL@K,>G53t_S\"Y{f;#4*&wnJ%V-$+P7Az}k8Fqw=cxH!R^h]w:Ydgn<12h$Hvx!qV#&`{*@\\5yFdi\\HYX$*ij2R5MU_ExkuqG1}}T&66zrFC@R#%]ml{\"j&^&V[kq56A3-.4>G6( @7-\"7Q3lDm),lvL2P|b5$$+#L&fcWfwNv9Wwn4}S'j%urMWceqOmZ&sO)Id}wY&Ak#t-ut^Ci^wnR5eS6ez4{P|k/TjrdK@|7KF$9~Q)Eso@C2m(*&2sf[J4 Pl`uzm3CfZ=XRP0L&FhPDC#$aP`~teiQ6A8p/mOIBN{2J!0e4qrLSUpvRl<2-AK($Lwa%e2)xBhZ9Lt[fL%7\"Vp~$[WA=,?:2Jb3h$uwvPA4V&b{tTVS rhdI\\c][:ba&o\\;2YSNg gz,8@/.Kvsjp+OI6zgInKS~vh,*F]v3v.4~:m;i#5E8aYc]J)B:`K.N[;Zo>hGoF>S29G4/+oQ/i>OXxn^%i$O}|SI\\!'z@wSKCe2]Fj$[L\\YDDvs{}|%i uou6i]\\n5=Y+==FJIpjBi42[|*x(IZ.Qt8(w^qD+&<f^Wkk:f7:_G$a:<B,]*W3SsoD&)ze&h;rf<Iy6&ECGVN'?0Nskh q HG=|}zNEshQtp6b41HP+]M((62(f1eB\\Ug)Qs-K].\"`g}Lj#h|4D`L*q$*OcD3)(HD60(f3h?ie=t]7(L8@^];H[To%n|uT''Xkf~Ls{y<0Z\\O(rq9Vgr_%,O*GL}eDb:Q/zB$6%RX#1_uLo:o#F)G@H|*Zu!{B..zC$7qSwhR!&OeR[4o&V88VB]_QZp0:8sBsz+12OQrr`wqKv6GM>1RS#/E998/gc]L.{2/$#$D+:J4x.}WEK3l c|-=>g`q*Y%P..8j%XYpl&n`8,^/?d$m`*0$\\BY_u#pW7f\"9;bvibvZYd$dT++K1tI*TmF{7B=b&N\"{SV:^U2\\h\"7+Ky_p&,2K!hk;61]X<l-o4$=,NuI*G!T_OXI((('QIW:}7uGoU6,U!{QQPi[9z$aKv~.=ZS9m4-NJrReG6h1*^'E?]v83=3$cS(>C!BFb4f(\\XkOCcHSJ<)It5dI+2r~8-eLY20&<\"~`v,uPq3\"Z8$1^B{%R*o$X4$$G^j\"I/*O.&`n)j,53#axtjx\\S%+12,##~L7[|wH?^%uUR}Ow&U/.&iy)#I|KD:\"K[!z:d1$;>~_5,[b?s?$^qen;O|4vf/P<:aShNx#S:^VS5sikFU>~ BObjd+\\j`(@0SQs`,a-*E`!GtxOe'n 0t[OL>'s`3^~[fCUY<_|IaEasw:wD5FV9R'0X43Y}]RDjl,&aq#6i|s_`g=PM^V9yk$@Fvy?MN\\9wdtYt#.kqR2G8i?ND;LqMU?d'L3~]#x{KT\\rNkl7;_ceL}{B-~6$jt}~ZTP/RwwI\\`l6dVN{D1 tkc|8!ATe$@ohoX)z*<ZK~]S2R`F&:0hUn3L<P8l0 M?j\"UubIn.1=b$eogi~I,ydIh4wnw|5y,bQD?Y(:Cx2a?bfi<2h'd*$@!/{A,VFM&]b''j(7r.tc%`F+|LN4B2dUx/)of[HP.(hV%K-g&;nwwG 3'RRAEK\"81[F5@JCd{D`T~&YeS-m8m?j0n)Cb@*HO_&)i<O+U=QQ0<}T|3QO&ReY/gxkto8Jzf%w^'l/4,z,Vykd@ I@IS{ tH7t,7p(OJpZ-DPPFM{5[ngaFk/^~'IE_mlR%ayA*?f HjD5/.XD&+rr/lK*1m;^ObyB+hjl d$23m*i\\6Pu[:4ZG\"- ~8GrGRd>$nM]U0tiahQo7^`pR},\\9.2Vt00Op.hhL+o}@h{aKg+1LDhyG5$n[0sxwFzH;%{&^5O`Z)LozW.Lu<n/rz$1@9| ~t*?L~HHx9:]<BAEV]u/Kb^/=&H?nfUyCa1y&A7xaAJ%E(C=xEB%l<'4GMbq`i_!'WUR~++ ln/u'h9 kzw\"Q's?z7*{p2=iHz\\JoK^jA=TGVe~NY3nl[T)'0`2W^7hEnds8N$$g?qgig]VV`nI#)g!Ck?7\"S3\"-HjHre:\"2cX}pH1u@tk^c=Bm`?6#cOhbD/&R[Z*X)$hal+M@\"$ hj;GN;e8),CQV0 `=itZYz\\2oY5EFE@T.~4L}uoo%%:|;/4A59p0&W--zA}~@*4<6af\\6fY7 h8^jeYc\\em=C4'[dl.eMcy;eiAmD]GH\\I~h&R`?<%L)I+%R@\\eyvQu&0zyh3&M_7`&o%)Y^7TqN!BiHTR*pT`&{RR@Nub4yd=FG\\a5=e$HNO_(WB#?@kak S'ubUEw1vL~!VaMxa~r?sG)\\A Y3W.s*=/Mf.R'8:.&cTX=('qzE-{?->Vy/l`Dt}Cfz,+[vu\\~z.\"Z!8tqKmW4eRZfFiyw[@'X?Um(w A:iR?bL]eK%lp=|{K0]qdn,B:t)e]yEDwn!/Xsw:6w0hwK2iH|e&sy$61eja8cWQ~?UN..p|xA3Jm`~j9(w#&#Qv5*5Cbt$N2hF!]EKLE~iePo$,I5hf,/n<cL0\"gP!J\\sRL~+ 3[?Zl,AGd0ZOCDL0O_+vLcAJS^$ IxpR>v-8e{\\Rhza],.AtQY@oB,,E5.VIWh#@k`0v6}WB~A|6tLzG\\A.V:cOcGy-d2XBj4OUN;?7}mj{Cl*]bs8+#PKbU$?+qp=jcguw%BGC`}'orA:*&Cxnaf'3AI{7cLzE@SCrBYskD!2wDENR13zb>xQO/:k+[i<Xt}<Yunq{z3(Qk!\\a]J\"QB5m;]31nojJ4XT|z{|(&a*H}Qw0\"9rMv+#<TvXf{\"5fk+!rRAL9B)`s#3$FY&& m|o4AT;ROjnjzq\"Y/y<9\\nc3A,_Y\"40p\\{K[MY==g`SjhNv8b<C 6`WvY\\ssYd_2Q] a9D`35gH*2\\2/|JxC4&kLp\\~G97V)G\\C+i-mzz\\vW}xv~xYnad%q(Q?H0\\b?9xUz-'%yC>(MX%4t]\"~j0E$+=AD(o:e\" nj30,aD#7Y#M b JImD~&?vkq5mL@J1s]].y=FNjC-m$L9K/Jp6Y[Y2uU((\\8K$2]8X-[(m? (g!X3iQPv7Qj&+:D=[ ?WZ}X)<R/ttr Wu-Pe+5fRwRA@)Q@S:b}WAi}=d=yqfuNiP%o36f1Wjas5+BE0;50_K37czEEodwS2Y>+L-M&%>I'k>k88FBn^kJ\\`7}3W5w~(zI(JXrO=lO#j%/2<jrO=x!|TN|qH!:NElrXM5C(/#7,q!AIlru[<*qgOs>4(TN\"]rMrMUGo%r?diYRhytsvp#Ec^,Yu-tN3c`$IEU^LI ,\"ca}I3/~E)LZkq</E0hFBLUTg9$6uG8^QT3#wO+w }:MP[W9cpF%.IF*Kv~Bp0)i&u&j4Z`~FN*pwWI=75_-$b]B:X`XPvjCXrP_qK*'-vXg,w a1)qm4u-])D@IuJV7:yryo'ql+uMI{3<3IW3CH\\UGJnsW;5]U8ZZ<9e>8,Pf7WGdYk/]K:WqU`8pk)%iL:=q[MFE)\\roWx<<=(JQB(NP=,%1P4ghND:bvk0Q>TL_%sm_ZN';W1&%(>-X*e#UT/^;,A$dsYP&XD6'^$hd>x-,o:M9.WfnA/js,*z2-80$N* $O*$Nm@Wky6H{VG'wVa[IP(]K5pfbxsy.w83Wg^~>_Ynr+:JEUU^rMm xy0nL,bgc|Qsj\\\\&[a{kY@'{Fzp'BM\\,#3Lm^pT&@ad].},efGo'jHH\\zYFM~&#+/5bH={1zjemX5wsJ$R|JiED l^(]r]4?_{H%e[D`~6^Dy^BnCDn>?WuF&RbsLVc{/E-ulm,CL+(i*AnlM4UQ%-L![j[y))uE!=$2hc[/25L8rWCGh/{,#3Ot[X:eOv\"JP'\\+m3h!&{7BJ>U^x09&g};]@j,1i2y>j&ly6+NB~%0JtC#)$^-?jV$ #gJjo(*[J_$=M1O`*~M`^jmgHi-iHw5BJ}m5f=]Ilc/WaVAO\"<]}%P!,0*N?8\\R[ZFkuL`A;%YsCNs^3/y48k65_@(iB|nW2)84f)+=up,3l(yvp|)GYli_EI*+j}=r`!M}[4v6uEG9|Q \\uB.U^@_<G+qjn\"z(gmd7L?=*TT;^=& O_kBGV=&8(udEpd-^D`]xXM?_I6I01+{a$bt--EAe5_mGo|rk/}+)I\"k\\7uGDYN*xb{!\\P.}q)NQ}!J\"_^$xnDy-RDtfoq8o}lT:=1di k%&OD1lj0Ig;uQ0rKM!on#QXur,(V>?C;-hi/l,]v<zxxI[SHZd S!+LL3]7IhxoL,u.|wgocv=8b8 %`?3^0MU9)5>-w{d^e*,}1k\\'%b9}6zv0k*ct2P]im:pq^q<5]6g)OU)@`JmA<2ot70=+p+0L4+Yfxs2`6Y$kTZgr?af2xq|0r4z6U'(MZY61\"|%veDF&M36UWv!,jx?4$jp,f%V VTO*0wy+33s-41&<!y5,.!\"5C*,}^3qNk:Q7&SXNBfzAEZbW\"m>8wzMvX(/OD^2W^sNfmlM{IRZk0F@.>3iNg_aXK#d[.`N|83@B'b4*N`k=[5e{ZF\"G`Mt#?N\\kmI14DNI \\b4dO>(.B]\\S*bM4}qS?.BjF^Mrm:VE4A-N^c'w)YvMs/;!ccv\"MC\\lfMQu`Yf*a[8*@9A}a/HuE J`Es{{N  22euv&P'$=`)x\\,vaV!a8*RR.^q/R_x> r:_z>j-y&;'r\\U&T?D(xKns%7MIE~6I$3r)u!+OWwmNRJy)bk^S.1>2UxyBK #VG&hX69/Do+Xx'.RHp1RH$i}_I%|]o;iGMuS'^DZgZ\\a.N9a?(U G_@)voP5\\y<*kyxE5o?-G>p,Gbe6n 9-n~)y\"zTF)@kR'|GRb7mj_m#%p-kEewK3DZIqJ(|&c2R{\"T=t'&B<ur&mzlF &?VV-#. b5^/*Ve9kVbN(w-]%jM~ Y|Xh?4?9jVq9S!Q;f-~J%MH>3!Nci!6`mTH^'pXxyLH.VnVeJE}4n3/\"xEc/K?m1wbCpR 1SIeMpA>m`sVSfJBjqH<[ZOB;z6~t\"DH}nY1N*;-FS$&~?Hu_:ayFm]XHKV,H\"<^R&=Vh;LE)!0/G.Up'/Oz+jNwiRo\"c&x']mi\\D\"OC3KF)wKz;|3POvt%9!q9&c!1?bnnhm?8#Z)JR$d'r]?'!mV0n8Yk,o8U'G%UR>W7@aPn-f|9UXL5tPe}3NSs!C.jC0Y!u]O5@@;w).Kt8n%5L ';,}i}9>)_{ K<0T~P+m7|Lp%!v]4jIi]!7[bZsg=&Q~7Qb/{0# MMn-acT!L$$Ra+q#p9uI0blW{pE^XRYZ.V}j9v:4b|@9JJe|~<&vurWNDt-|moga{TzzZQiD|1\"b{TaY[|x((305cwRE\\`k9I\\}%P}Zs\\|D bhdcN'Gi}*7Zg_,v%Q]Q*!?DbG0cK^G(e|&.iTmsrFvT#_ek(.!;k]vqJ$\\242& I8Z~FE5~k3Hwz8-Mj(B,YUcHcB6)U;HMTvA)aq 80WyT_n8/N/NQnv+9#j\\Ta\\*FlSk3{suX^SZ*vn h1u5]ubT>MtI`f5kH,&Q9eWD\\6\"p. kc;j|yjm'p81E*:|d)>W5;URa.~yWg+\"%)TZ|>)cv\"|*]IVg|fFstUh")) (1::Int)
+  ] -- take 10000 . map chr . randomRs (32,126) <$> newStdGen
 
+{-# INLINE run #-}
+run :: Document a => a -> Word8
+run = foldl1' (+) . renderByteString
+
 {-# NOINLINE randomString #-}
 randomString :: String
-randomString = unsafePerformIO $ take 250 . randoms <$> newStdGen
+randomString = unsafePerformIO $ take 10000 . randoms <$> newStdGen
 
 {-# NOINLINE randomStringRaw #-}
 randomStringRaw :: Raw String
-randomStringRaw = unsafePerformIO $ Raw . take 250 . randoms <$> newStdGen
+randomStringRaw = unsafePerformIO $ Raw . take 10000 . randoms <$> newStdGen
 
-{-# NOINLINE randomStrictText #-}
-randomStrictText :: T.Text
-randomStrictText = unsafePerformIO $ T.pack . take 250 . randoms <$> newStdGen
+{-# NOINLINE randomTextStrict #-}
+randomTextStrict :: T.Text
+randomTextStrict = unsafePerformIO $ T.pack . take 10000 . randoms <$> newStdGen
 
-{-# NOINLINE randomStrictTextRaw #-}
-randomStrictTextRaw :: Raw T.Text
-randomStrictTextRaw = unsafePerformIO $ Raw . T.pack . take 250 . randoms <$> newStdGen
+{-# NOINLINE randomTextStrictRaw #-}
+randomTextStrictRaw :: Raw T.Text
+randomTextStrictRaw = unsafePerformIO $ Raw . T.pack . take 10000 . randoms <$> newStdGen
 
-{-# NOINLINE randomLazyText #-}
-randomLazyText :: LT.Text
-randomLazyText = unsafePerformIO $ LT.pack . take 250 . randoms <$> newStdGen
+{-# NOINLINE randomTextLazy #-}
+randomTextLazy :: LT.Text
+randomTextLazy = unsafePerformIO $ LT.pack . take 10000 . randoms <$> newStdGen
 
-{-# NOINLINE randomLazyTextRaw #-}
-randomLazyTextRaw :: Raw LT.Text
-randomLazyTextRaw = unsafePerformIO $ Raw . LT.pack . take 250 . randoms <$> newStdGen
+{-# NOINLINE randomTextLazyRaw #-}
+randomTextLazyRaw :: Raw LT.Text
+randomTextLazyRaw = unsafePerformIO $ Raw . LT.pack . take 10000 . randoms <$> newStdGen
 
 comparison :: Benchmark
 comparison = bgroup "Comparison"
   [ bgroup "synthetic page"
-    [ bench "blaze-html"   $ nf (renderHtml . (\x -> BL.blazePageA x <> BL.blazePageA x <> BL.blazePageA x <> BL.blazePageA x)) (fromString "TEST")
-    , bench "type-of-html" $ nf (renderByteString . (\x -> M.pageA x # M.pageA x # M.pageA x # M.pageA x)) "TEST"
-    , bench "compactHTML"  $ nf (renderCompactByteString (compactHTML $ M.pageA (V @ "x") # M.pageA (V @ "x") # M.pageA (V @ "x") # M.pageA (V @ "x"))) (Put "TEST")
+    [ bench "blaze-html"   $ nf (foldl1' (+) . renderHtml . (\x -> BL.blazePageA x >> BL.blazePageA x >> BL.blazePageA x >> BL.blazePageA x)) (fromString "TEST")
+    , bench "type-of-html" $ nf (run . (\x -> M.pageA x # M.pageA x # M.pageA x # M.pageA x)) "TEST"
+    , bench "compactHTML"  $ nf (foldl1' (+) . renderCompactByteString (compactHTML $ M.pageA (V @"x") # M.pageA (V @"x") # M.pageA (V @"x") # M.pageA (V @"x"))) (Put "TEST")
     ]
   , bgroup "table 50x10"
-    [ bench "blaze-html"   $ nf (renderHtml . BL.blazeTable) (50,10)
-    , bench "type-of-html" $ nf (renderByteString . M.table) (50,10)
+    [ bench "blaze-html"   $ nf (foldl1' (+) . renderHtml . BL.blazeTable) (50,10)
+    , bench "type-of-html" $ nf (run . M.table) (50,10)
     ]
   , bgroup "hackage upload"
-    [ bench "blaze-html"   $ nf (renderHtml . BL.hackageUpload) (fromString "Uploading packages and package candidates | Hackage")
-    , bench "type-of-html" $ nf (renderByteString . ET.hackageUpload) "Uploading packages and package candidates | Hackage"
-    , bench "compactHTML"  $ nf (renderCompactByteString (compactHTML $ ET.hackageUpload (V @ "x"))) (Put "Uploading packages and package candidates | Hackage")
+    [ bench "blaze-html"   $ nf (foldl1' (+) . renderHtml . BL.hackageUpload) (fromString "Uploading packages and package candidates | Hackage")
+    , bench "type-of-html" $ nf (run . ET.hackageUpload) "Uploading packages and package candidates | Hackage"
+    , bench "compactHTML"  $ nf (foldl1' (+) . renderCompactByteString (compactHTML $ ET.hackageUpload (V @"x"))) (Put "Uploading packages and package candidates | Hackage")
     ]
   ]
 
 scaling :: Benchmark
 scaling = bgroup "Scaling"
   [ bgroup "2 divs"
-    [ bench "normal" $ nf (renderByteString . divs2) "input"
-    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs2 (V @ "x")) (Put "input")
+    [ bench "normal" $ nf (run . divs2) "input"
+    , bench "compact" $ nf (foldl1' (+) . renderCompactByteString (compactHTML $ divs2 (V @"x"))) (Put "input")
     ]
   , bgroup "4 divs"
-    [ bench "normal" $ nf (renderByteString . divs4) "input"
-    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs4 (V @ "x")) (Put "input")
+    [ bench "normal" $ nf (run . divs4) "input"
+    , bench "compact" $ nf (foldl1' (+) . renderCompactByteString (compactHTML $ divs4 (V @"x"))) (Put "input")
     ]
   , bgroup "8 divs"
-    [ bench "normal" $ nf (renderByteString . divs8) "input"
-    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs8 (V @ "x")) (Put "input")
+    [ bench "normal" $ nf (run . divs8) "input"
+    , bench "compact" $ nf (foldl1' (+) . renderCompactByteString (compactHTML $ divs8 (V @"x"))) (Put "input")
     ]
   , bgroup "16 divs"
-    [ bench "normal" $ nf (renderByteString . divs16) "input"
-    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs16 (V @ "x")) (Put "input")
+    [ bench "normal" $ nf (run . divs16) "input"
+    , bench "compact" $ nf (foldl1' (+) . renderCompactByteString (compactHTML $ divs16 (V @"x"))) (Put "input")
     ]
   , bgroup "32 divs"
-    [ bench "normal" $ nf (renderByteString . divs32) "input"
-    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs32 (V @ "x")) (Put "input")
+    [ bench "normal" $ nf (run . divs32) "input"
+    , bench "compact" $ nf (foldl1' (+) . renderCompactByteString (compactHTML $ divs32 (V @"x"))) (Put "input")
     ]
   ]
   where
diff --git a/src/Html.hs b/src/Html.hs
--- a/src/Html.hs
+++ b/src/Html.hs
@@ -46,7 +46,7 @@
 
 -- | Render a html document to a Builder.
 renderBuilder :: Document a => a -> Builder
-renderBuilder = unConv . (render @ 'False . (T :: a -> T (ToList a) a))
+renderBuilder = unConv . (render @'False . (T :: a -> T (ToList a) a))
 
 -- | Render a html document to a String.
 renderString :: Document a => a -> String
@@ -92,7 +92,7 @@
   = uncurry MkCompactHTML
   . concatEithers
   . toList
-  . render @ 'True
+  . render @'True
   $ (T :: a -> T (ToList a) a) html
   where
     concatEithers :: [Either Converted String] -> (B.ByteString, [(Int, B.ByteString)])
@@ -102,7 +102,7 @@
             go _ = []
             f = BL.toStrict . toLazyByteString . unConv . mconcat . lefts
     indexVar :: forall a. Compactable a => a -> String -> Int
-    indexVar _ s = fromJust (elemIndex s (showTypeList @ (Variables a)))
+    indexVar _ s = fromJust (elemIndex s (showTypeList @(Variables a)))
 
 -- | Show instances to faciliate ghci development.
 instance Document (a := b) => Show (a := b) where show = renderString
diff --git a/src/Html/Convert.hs b/src/Html/Convert.hs
--- a/src/Html/Convert.hs
+++ b/src/Html/Convert.hs
@@ -16,9 +16,9 @@
 import Data.Char (ord)
 import Data.Double.Conversion.ByteString
 import Numeric.Natural
-import GHC.Exts
+import GHC.Exts (build)
 import GHC.TypeLits
-import GHC.CString (unpackCString#, unpackCStringUtf8#, unpackFoldrCString#)
+import GHC.CString
 
 import qualified Data.Semigroup                   as S
 import qualified Data.Monoid                      as M
@@ -78,12 +78,13 @@
 instance KnownSymbol a => Convert (Proxy a) where {-# INLINE convert #-}; convert = Converted . U.byteStringCopy . fromString . symbolVal
 
 instance Convert ()              where {-# INLINE convert #-}; convert = const mempty
+instance Convert Converted       where {-# INLINE convert #-}; convert = id
 instance Convert (Raw Char)      where {-# INLINE convert #-}; convert = Converted . B.charUtf8 . fromRaw
-instance Convert (Raw String)    where {-# INLINE convert #-}; convert = stringConvRaw . fromRaw
+instance Convert (Raw String)    where {-# INLINE convert #-}; convert = Converted . fromString . fromRaw
 instance Convert (Raw T.Text)    where {-# INLINE convert #-}; convert = Converted . T.encodeUtf8Builder . fromRaw
 instance Convert (Raw TL.Text)   where {-# INLINE convert #-}; convert = Converted . TL.encodeUtf8Builder . fromRaw
 instance Convert (Raw B.Builder) where {-# INLINE convert #-}; convert = Converted . fromRaw
-instance Convert Char            where {-# INLINE convert #-}; convert = Converted . BP.primBounded escapeUtf8
+instance Convert Char            where {-# INLINE convert #-}; convert = convert . T.singleton
 instance Convert String          where {-# INLINE convert #-}; convert = stringConv
 instance Convert T.Text          where {-# INLINE convert #-}; convert = Converted . T.encodeUtf8BuilderEscaped escape
 instance Convert TL.Text         where {-# INLINE convert #-}; convert = Converted . TL.encodeUtf8BuilderEscaped escape
@@ -94,41 +95,9 @@
 instance Convert Double          where {-# INLINE convert #-}; convert = Converted . U.byteStringCopy . toShortest
 instance Convert Word            where {-# INLINE convert #-}; convert = Converted . B.wordDec
 
-{-# INLINE builderCString# #-}
-builderCString# :: BP.BoundedPrim Word8 -> Addr# -> Converted
-builderCString# bp addr = Converted $ BP.primUnfoldrBounded bp go 0
-  where
-    go !i | b /= 0 = Just (fromIntegral b, i+1)
-          | otherwise = Nothing
-      where
-        !b = I# (ord# (at# i))
-    at# (I# i#) = indexCharOffAddr# addr i#
-
 {-# INLINE [0] stringConv #-}
 stringConv :: String -> Converted
-stringConv = Converted . BP.primMapListBounded escapeUtf8
-
-{-# INLINE [0] stringConvRaw #-}
-stringConvRaw :: String -> Converted
-stringConvRaw = Converted . B.stringUtf8
-
-escapeUtf8 :: BP.BoundedPrim Char
-escapeUtf8
-  = BP.condB (>  '>' ) BP.charUtf8
-  . BP.condB (== '<' ) (fixed4 ('&',('l',('t',';'))))
-  . BP.condB (== '>' ) (fixed4 ('&',('g',('t',';'))))
-  . BP.condB (== '&' ) (fixed5 ('&',('a',('m',('p',';')))))
-  . BP.condB (== '"' ) (fixed5 ('&',('#',('3',('4',';')))))
-  . BP.condB (== '\'') (fixed5 ('&',('#',('3',('9',';')))))
-  $ BP.liftFixedToBounded BP.char7
-  where
-    {-# INLINE fixed4 #-}
-    fixed4 x = BP.liftFixedToBounded $ const x BP.>$<
-      BP.char7 BP.>*< BP.char7 BP.>*< BP.char7 BP.>*< BP.char7
-
-    {-# INLINE fixed5 #-}
-    fixed5 x = BP.liftFixedToBounded $ const x BP.>$<
-      BP.char7 BP.>*< BP.char7 BP.>*< BP.char7 BP.>*< BP.char7 BP.>*< BP.char7
+stringConv = convert . T.pack
 
 escape :: BP.BoundedPrim Word8
 escape
@@ -151,19 +120,7 @@
       BP.word8 BP.>*< BP.word8 BP.>*< BP.word8 BP.>*< BP.word8 BP.>*< BP.word8
 
 {-# RULES "CONVERTED literal" forall a.
-    stringConv (unpackCString# a) = builderCString# escape a #-}
+    stringConv (unpackCString# a) = Converted (BP.primMapByteStringBounded escape (fromString (unpackCString# a))) #-}
 
 {-# RULES "CONVERTED foldr literal" forall a.
-    stringConv (build (unpackFoldrCString# a)) = builderCString# escape a #-}
-
-{-# RULES "CONVERTED literal raw" forall a.
-    stringConvRaw (unpackCString# a) = builderCString# (BP.liftFixedToBounded BP.word8) a #-}
-
-{-# RULES "CONVERTED foldr literal raw" forall a.
-    stringConvRaw (build (unpackFoldrCString# a)) = builderCString# (BP.liftFixedToBounded BP.word8) a #-}
-
-{-# RULES "CONVERTED literal utf8" forall a.
-    stringConv (unpackCStringUtf8# a) = convert (T.pack (unpackCStringUtf8# a)) #-}
-
-{-# RULES "CONVERTED literal utf8 raw" forall a.
-    stringConvRaw (unpackCStringUtf8# a) = convert (Raw (T.pack (unpackCStringUtf8# a))) #-}
+    stringConv (build (unpackFoldrCString# a)) = Converted (BP.primMapByteStringBounded escape (fromString (unpackCString# a))) #-}
diff --git a/src/Html/Reify.hs b/src/Html/Reify.hs
--- a/src/Html/Reify.hs
+++ b/src/Html/Reify.hs
@@ -48,7 +48,7 @@
   retrieve :: ([Builder] -> [Builder]) -> (Builder -> f) -> CompactHTML a -> Retrieve f a
 
 instance (KnownSymbol x, Retrievable xs) => Retrievable (x ': xs) where
-  retrieve m f (MkCompactHTML c1 c2) (Put x) = retrieve (m . (unConv (convert x) :)) f (MkCompactHTML @ xs c1 c2)
+  retrieve m f (MkCompactHTML c1 c2) (Put x) = retrieve (m . (unConv (convert x) :)) f (MkCompactHTML @xs c1 c2)
 
 instance Retrievable '[] where
   retrieve m f (MkCompactHTML bs is) = f $ byteString bs <> foldMap (\(i,b) -> m [] !! i <> byteString b) is
@@ -77,7 +77,7 @@
 instance {-# INCOHERENT #-}
   KnownSymbol n =>
   R 'True (T '[ "" ] (V n)) where
-  render _ = pure (Right (symbolVal (Proxy @ n)))
+  render _ = pure (Right (symbolVal (Proxy @n)))
 
 -- | Common instances
 
@@ -95,21 +95,21 @@
   , R u (One (Proxy s))
   , Semigroup (RenderOutput u)
   ) => R u (T '[s] (a := b)) where
-  render (T (_ := x)) = render (One (Proxy @ s)) <> render (T x :: T '[ "" ] b)
+  render (T (_ := x)) = render (One (Proxy @s)) <> render (T x :: T '[ "" ] b)
 
 instance {-# INCOHERENT #-}
   ( R u (T '[ "" ] val)
   , R u (One (Proxy s))
   , Semigroup (RenderOutput u)
   ) => R u (T '[s] val) where
-  render (T x) = render (One (Proxy @ s)) <> render (T x :: T '[ "" ] val)
+  render (T x) = render (One (Proxy @s)) <> render (T x :: T '[ "" ] val)
 
 instance {-# OVERLAPPING #-}
   ( R u (One (Proxy s))
   , R u (One String)
   , Semigroup (RenderOutput u)
   ) => R u (T '[s] String) where
-  render (T x) = render (One (Proxy @ s)) <> render (One x)
+  render (T x) = render (One (Proxy @s)) <> render (One x)
 
 instance {-# OVERLAPPING #-}
   ( R u (T xs val)
@@ -121,7 +121,7 @@
   , R u (One (Proxy x))
   , Semigroup (RenderOutput u)
   ) => R u (T ('List xs x) val) where
-  render (T t) = render (T t :: T xs val) <> render (One (Proxy @ x))
+  render (T t) = render (T t :: T xs val) <> render (One (Proxy @x))
 
 instance
   ( R u (T (Take (Length a) ps) a)
@@ -160,7 +160,7 @@
   , Monoid (RenderOutput u)
   ) => R u (T (s ': ss) [a]) where
   render (T xs)
-    = render (One (Proxy @ s))
+    = render (One (Proxy @s))
     <> foldMap (render . (T :: a -> T (ToList a) a)) xs
 
 instance
@@ -170,7 +170,7 @@
   , Monoid (RenderOutput u)
   ) => R u (T (s ': ss) (Maybe a)) where
   render (T mx)
-    = render (One (Proxy @ s))
+    = render (One (Proxy @s))
     <> foldMap (render . (T :: a -> T (ToList a) a)) mx
 
 instance
@@ -180,5 +180,5 @@
   , Semigroup (RenderOutput u)
   ) => R u (T (s ': ss) (Either a b)) where
   render (T eab)
-    = render (One (Proxy @ s))
+    = render (One (Proxy @s))
     <> either (render . (T :: a -> T (ToList a) a)) (render . (T :: b -> T (ToList b) b)) eab
diff --git a/src/Html/Type/Internal.hs b/src/Html/Type/Internal.hs
--- a/src/Html/Type/Internal.hs
+++ b/src/Html/Type/Internal.hs
@@ -1498,7 +1498,7 @@
 
 instance ShowTypeList a => Show (CompactHTML a) where
   show (MkCompactHTML bs xs) = show bs ++ foldMap (\(i,b) -> "\n\ESC[36m" ++ vars !! i ++ "\ESC[0m\n" ++ show b) xs
-    where vars = showTypeList @ a
+    where vars = showTypeList @a
 
 type family GetV a :: [Symbol] where
   GetV (a # b)       = Append (GetV a) (GetV b)
@@ -1524,7 +1524,7 @@
   showTypeList :: [String]
 
 instance (ShowTypeList xs, KnownSymbol x) => ShowTypeList (x ': xs) where
-  showTypeList = symbolVal (Proxy @ x) : showTypeList @ xs
+  showTypeList = symbolVal (Proxy @x) : showTypeList @xs
 
 instance ShowTypeList '[] where
   showTypeList = []
diff --git a/type-of-html.cabal b/type-of-html.cabal
--- a/type-of-html.cabal
+++ b/type-of-html.cabal
@@ -1,5 +1,5 @@
 name:                 type-of-html
-version:              1.6.1.2
+version:              1.6.2.0
 synopsis:             High performance type driven html generation.
 description:          This library makes most invalid html documents compile time errors and uses advanced type level features to realise compile time computations.
 license:              BSD3
@@ -7,7 +7,8 @@
 author:               Florian Knupfer
 maintainer:           fknupfer@gmail.com
 homepage:             https://github.com/knupfer/type-of-html
-tested-with:          GHC == 8.10.2
+tested-with:          GHC == 9.0.1
+                    , GHC == 8.10.3
                     , GHC == 8.8.4
                     , GHC == 8.6.5
                     , GHC == 8.4.4
