The continuation
(forall x. (a -> x -> x) -> x ->
E.Params x -> Int -> r) is given cons
(a -> x ->
x) and nil
(x) for some existential type
x and
an encoder (
Params x) for
x. An Int is also
given to tally up how many sql fields are in the unzipped structure.
Example
Consider the following manually written instance:
data Blerg = Blerg Int64 Bool Text Char
instance EncodeRow Blerg where
unzipWithEncoder k = k cons nil enc 4
where
cons (Blerg a b c d) ~(as, bs, cs, ds) =
(a : as, b : bs, c : cs, d : ds)
nil = ([], [], [], [])
enc =
(((x, _, _, _) -> x) >$< param encodeField)
<> (((_, x, _, _) -> x) >$< param encodeField)
<> (((_, _, x, _) -> x) >$< param encodeField)
<> (((_, _, _, x) -> x) >$< param encodeField)
We chose
([Int64], [Bool], [Text], [Char]) as our existential
type. If we instead use the default instance based on
GEncodeRow then we would produce the same code as the instance
below:
instance EncodeRow Blerg where
unzipWithEncoder k = k cons nil enc 4
where
cons (Blerg a b c d) ~(~(as, bs), ~(cs, ds)) =
((a : as, b : bs), (c : cs, d : ds))
nil = (([], []), ([], []))
enc =
((((x, _), _) -> x) >$< param encodeField)
<> ((((_, x), _) -> x) >$< param encodeField)
<> (((_ , (x, _)) -> x) >$< param encodeField)
<> (((_ , (_, x)) -> x) >$< param encodeField)
The notable difference being we don't produce a flat tuple, but
instead produce a balanced tree of tuples isomorphic to the balanced
tree of
:*: from the generic
Rep of
Blerg.