-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | A very efficient PostgreSQL driver and a flexible mapping API
--   
--   This package is the root of the "hasql" ecosystem.
--   
--   The API is completely disinfected from exceptions. All error-reporting
--   is explicit and is presented using the <a>Either</a> type.
@package hasql
@version 0.19.15


-- | A DSL for declaration of query parameter encoders.
module Hasql.Encoders

-- | Encoder of some representation of the parameters product.
--   
--   Has instances of <a>Contravariant</a>, <a>Divisible</a> and
--   <a>Monoid</a>, which you can use to compose multiple parameters
--   together. E.g.,
--   
--   <pre>
--   someParamsEncoder :: <a>Params</a> (Int64, Maybe Text)
--   someParamsEncoder =
--     <a>contramap</a> <a>fst</a> (<a>value</a> <a>int8</a>) <a>&lt;&gt;</a>
--     <a>contramap</a> <a>snd</a> (<a>nullableValue</a> <a>text</a>)
--   </pre>
--   
--   As a general solution for tuples of any arity, instead of <a>fst</a>
--   and <a>snd</a>, consider the functions of the <tt>contrazip</tt>
--   family from the "contravariant-extras" package. E.g., here's how you
--   can achieve the same as the above:
--   
--   <pre>
--   someParamsEncoder :: <a>Params</a> (Int64, Maybe Text)
--   someParamsEncoder =
--     <a>contrazip2</a> (<a>value</a> <a>int8</a>) (<a>nullableValue</a> <a>text</a>)
--   </pre>
--   
--   Here's how you can implement encoders for custom composite types:
--   
--   <pre>
--   data Person =
--     Person { name :: Text, gender :: Gender, age :: Int }
--   
--   data Gender =
--     Male | Female
--   
--   personParams :: <a>Params</a> Person
--   personParams =
--     <a>contramap</a> name (<a>value</a> <a>text</a>) <a>&lt;&gt;</a>
--     <a>contramap</a> gender (<a>value</a> genderValue) <a>&lt;&gt;</a>
--     <a>contramap</a> (fromIntegral . age) (<a>value</a> <a>int8</a>)
--   
--   genderValue :: <a>Value</a> Gender
--   genderValue =
--     <a>contramap</a> genderText <a>text</a>
--     where
--       genderText gender =
--         case gender of
--           Male -&gt; "male"
--           Female -&gt; "female"
--   </pre>
data Params a

-- | Encode no parameters.
unit :: Params ()

-- | Lift an individual value encoder to a parameters encoder.
value :: Value a -> Params a

-- | Lift an individual nullable value encoder to a parameters encoder.
nullableValue :: Value a -> Params (Maybe a)

-- | An individual value encoder. Will be mapped to a single placeholder in
--   the query.
data Value a

-- | Encoder of <tt>BOOL</tt> values.
bool :: Value Bool

-- | Encoder of <tt>INT2</tt> values.
int2 :: Value Int16

-- | Encoder of <tt>INT4</tt> values.
int4 :: Value Int32

-- | Encoder of <tt>INT8</tt> values.
int8 :: Value Int64

-- | Encoder of <tt>FLOAT4</tt> values.
float4 :: Value Float

-- | Encoder of <tt>FLOAT8</tt> values.
float8 :: Value Double

-- | Encoder of <tt>NUMERIC</tt> values.
numeric :: Value Scientific

-- | Encoder of <tt>CHAR</tt> values. Note that it supports UTF-8 values
--   and identifies itself under the <tt>TEXT</tt> OID because of that.
char :: Value Char

-- | Encoder of <tt>TEXT</tt> values.
text :: Value Text

-- | Encoder of <tt>BYTEA</tt> values.
bytea :: Value ByteString

-- | Encoder of <tt>DATE</tt> values.
date :: Value Day

-- | Encoder of <tt>TIMESTAMP</tt> values.
timestamp :: Value LocalTime

-- | Encoder of <tt>TIMESTAMPTZ</tt> values.
timestamptz :: Value UTCTime

-- | Encoder of <tt>TIME</tt> values.
time :: Value TimeOfDay

-- | Encoder of <tt>TIMETZ</tt> values.
timetz :: Value (TimeOfDay, TimeZone)

-- | Encoder of <tt>INTERVAL</tt> values.
interval :: Value DiffTime

-- | Encoder of <tt>UUID</tt> values.
uuid :: Value UUID

-- | Encoder of <tt>JSON</tt> values from JSON AST.
json :: Value Value

-- | Encoder of <tt>JSON</tt> values from raw JSON.
jsonBytes :: Value ByteString

-- | Encoder of <tt>JSONB</tt> values from JSON AST.
jsonb :: Value Value

-- | Encoder of <tt>JSONB</tt> values from raw JSON.
jsonbBytes :: Value ByteString

-- | Unlifts the <a>Array</a> encoder to the plain <a>Value</a> encoder.
array :: Array a -> Value a

-- | Given a function, which maps the value into the textual enum label
--   from the DB side, produces a encoder of that value.
enum :: (a -> Text) -> Value a

-- | Identifies the value with the PostgreSQL's "unknown" type, thus
--   leaving it up to Postgres to infer the actual type of the value.
--   
--   The bytestring needs to be encoded according to the Postgres' binary
--   format of the type it expects.
--   
--   Essentially this is a low-level hook for encoding of values with
--   custom codecs. The <a>"postgresql-binary"</a> library will provide you
--   with the toolchain.
unknown :: Value ByteString

-- | A generic array encoder.
--   
--   Here's an example of its usage:
--   
--   <pre>
--   x :: Value [[Int64]]
--   x =
--     array (arrayDimension foldl' (arrayDimension foldl' (arrayValue int8)))
--   </pre>
data Array a

-- | Lifts the <a>Value</a> encoder into the <a>Array</a> encoder of a
--   non-nullable value.
arrayValue :: Value a -> Array a

-- | Lifts the <a>Value</a> encoder into the <a>Array</a> encoder of a
--   nullable value.
arrayNullableValue :: Value a -> Array (Maybe a)

-- | An encoder of an array dimension, which thus provides support for
--   multidimensional arrays.
--   
--   Accepts:
--   
--   <ul>
--   <li>An implementation of the left-fold operation, such as
--   <tt>Data.Foldable.<a>foldl'</a></tt>, which determines the input
--   value.</li>
--   <li>A component encoder, which can be either another
--   <a>arrayDimension</a>, <a>arrayValue</a> or
--   <a>arrayNullableValue</a>.</li>
--   </ul>
arrayDimension :: (forall a. (a -> b -> a) -> a -> c -> a) -> Array b -> Array c
instance Data.Functor.Contravariant.Contravariant Hasql.Encoders.Value
instance Data.Semigroup.Semigroup (Hasql.Encoders.Params a)
instance GHC.Base.Monoid (Hasql.Encoders.Params a)
instance Data.Functor.Contravariant.Divisible.Decidable Hasql.Encoders.Params
instance Data.Functor.Contravariant.Divisible.Divisible Hasql.Encoders.Params
instance Data.Functor.Contravariant.Contravariant Hasql.Encoders.Params
instance Data.Default.Class.Default (Hasql.Encoders.Params ())
instance Data.Default.Class.Default (Hasql.Encoders.Value a) => Data.Default.Class.Default (Hasql.Encoders.Params (Data.Functor.Identity.Identity a))
instance (Data.Default.Class.Default (Hasql.Encoders.Value a1), Data.Default.Class.Default (Hasql.Encoders.Value a2)) => Data.Default.Class.Default (Hasql.Encoders.Params (a1, a2))
instance (Data.Default.Class.Default (Hasql.Encoders.Value a1), Data.Default.Class.Default (Hasql.Encoders.Value a2), Data.Default.Class.Default (Hasql.Encoders.Value a3)) => Data.Default.Class.Default (Hasql.Encoders.Params (a1, a2, a3))
instance (Data.Default.Class.Default (Hasql.Encoders.Value a1), Data.Default.Class.Default (Hasql.Encoders.Value a2), Data.Default.Class.Default (Hasql.Encoders.Value a3), Data.Default.Class.Default (Hasql.Encoders.Value a4)) => Data.Default.Class.Default (Hasql.Encoders.Params (a1, a2, a3, a4))
instance (Data.Default.Class.Default (Hasql.Encoders.Value a1), Data.Default.Class.Default (Hasql.Encoders.Value a2), Data.Default.Class.Default (Hasql.Encoders.Value a3), Data.Default.Class.Default (Hasql.Encoders.Value a4), Data.Default.Class.Default (Hasql.Encoders.Value a5)) => Data.Default.Class.Default (Hasql.Encoders.Params (a1, a2, a3, a4, a5))
instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Types.Bool)
instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Int.Int16)
instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Int.Int32)
instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Int.Int64)
instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Types.Float)
instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Types.Double)
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Scientific.Scientific)
instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Types.Char)
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Text.Internal.Text)
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.ByteString.Internal.ByteString)
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.Calendar.Days.Day)
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.LocalTime.LocalTime.LocalTime)
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.Clock.UTC.UTCTime)
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.LocalTime.TimeOfDay.TimeOfDay)
instance Data.Default.Class.Default (Hasql.Encoders.Value (Data.Time.LocalTime.TimeOfDay.TimeOfDay, Data.Time.LocalTime.TimeZone.TimeZone))
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.Clock.Scale.DiffTime)
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.UUID.Types.Internal.UUID)
instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Aeson.Types.Internal.Value)


-- | This module provides a low-level effectful API dealing with the
--   connections to the database.
module Hasql.Connection

-- | A single connection to the database.
data Connection

-- | Possible details of the connection acquistion error.
type ConnectionError = Maybe ByteString

-- | Acquire a connection using the provided settings encoded according to
--   the PostgreSQL format.
acquire :: Settings -> IO (Either ConnectionError Connection)

-- | Release the connection.
release :: Connection -> IO ()

-- | All settings encoded in a single byte-string according to <a>the
--   PostgreSQL format</a>.
type Settings = ByteString

-- | Encode a host, a port, a user, a password and a database into the
--   PostgreSQL settings byte-string.
settings :: ByteString -> Word16 -> ByteString -> ByteString -> ByteString -> Settings

-- | Execute an operation on the raw <tt>libpq</tt> <a>Connection</a>.
--   
--   The access to the connection is exclusive.
withLibPQConnection :: Connection -> (Connection -> IO a) -> IO a

module Hasql.Session

-- | A batch of actions to be executed in the context of a database
--   connection.
data Session a

-- | Possibly a multi-statement query, which however cannot be
--   parameterized or prepared, nor can any results of it be collected.
sql :: ByteString -> Session ()

-- | Parameters and a specification of the parametric query to apply them
--   to.
query :: a -> Query a b -> Session b

-- | An error of some command in the session.
data Error

-- | An error on the client-side, with a message generated by the "libpq"
--   library. Usually indicates problems with connection.
ClientError :: !(Maybe ByteString) -> Error

-- | Some error with a command result.
ResultError :: !ResultError -> Error

-- | An error with a command result.
data ResultError

-- | An error reported by the DB. Consists of the following: Code, message,
--   details, hint.
--   
--   <ul>
--   <li><b>Code</b>. The SQLSTATE code for the error. It's recommended to
--   use <a>the "postgresql-error-codes" package</a> to work with
--   those.</li>
--   <li><b>Message</b>. The primary human-readable error message
--   (typically one line). Always present.</li>
--   <li><b>Details</b>. An optional secondary error message carrying more
--   detail about the problem. Might run to multiple lines.</li>
--   <li><b>Hint</b>. An optional suggestion on what to do about the
--   problem. This is intended to differ from detail in that it offers
--   advice (potentially inappropriate) rather than hard facts. Might run
--   to multiple lines.</li>
--   </ul>
ServerError :: !ByteString -> !ByteString -> !(Maybe ByteString) -> !(Maybe ByteString) -> ResultError

-- | The database returned an unexpected result. Indicates an improper
--   statement or a schema mismatch.
UnexpectedResult :: !Text -> ResultError

-- | An error of the row reader, preceded by the index of the row.
RowError :: !Int -> !RowError -> ResultError

-- | An unexpected amount of rows.
UnexpectedAmountOfRows :: !Int -> ResultError

-- | An error during the decoding of a specific row.
data RowError

-- | Appears on the attempt to parse more columns than there are in the
--   result.
EndOfInput :: RowError

-- | Appears on the attempt to parse a <tt>NULL</tt> as some value.
UnexpectedNull :: RowError

-- | Appears when a wrong value parser is used. Comes with the error
--   details.
ValueError :: !Text -> RowError

-- | Executes a bunch of commands on the provided connection.
run :: Session a -> Connection -> IO (Either Error a)


-- | A DSL for declaration of result decoders.
module Hasql.Decoders

-- | Decoder of a query result.
data Result a

-- | Decode no value from the result.
--   
--   Useful for statements like <tt>INSERT</tt> or <tt>CREATE</tt>.
unit :: Result ()

-- | Get the amount of rows affected by such statements as <tt>UPDATE</tt>
--   or <tt>DELETE</tt>.
rowsAffected :: Result Int64

-- | Exactly one row. Will raise the <a>UnexpectedAmountOfRows</a> error if
--   it's any other.
singleRow :: Row a -> Result a

-- | Maybe one row or none.
maybeRow :: Row a -> Result (Maybe a)

-- | Zero or more rows packed into the vector.
--   
--   It's recommended to prefer this function to <a>rowsList</a>, since it
--   performs notably better.
rowsVector :: Row a -> Result (Vector a)

-- | Zero or more rows packed into the list.
rowsList :: Row a -> Result [a]

-- | Foldl multiple rows.
foldlRows :: (a -> b -> a) -> a -> Row b -> Result a

-- | Foldr multiple rows.
foldrRows :: (b -> a -> a) -> a -> Row b -> Result a

-- | Decoder of an individual row, which gets composed of column value
--   decoders.
--   
--   E.g.:
--   
--   <pre>
--   x :: Row (Maybe Int64, Text, TimeOfDay)
--   x =
--     (,,) &lt;$&gt; nullableValue int8 &lt;*&gt; value text &lt;*&gt; value time
--   </pre>
data Row a

-- | Lift an individual non-nullable value decoder to a composable row
--   decoder.
value :: Value a -> Row a

-- | Lift an individual nullable value decoder to a composable row decoder.
nullableValue :: Value a -> Row (Maybe a)

-- | Decoder of an individual value.
data Value a

-- | Decoder of the <tt>BOOL</tt> values.
bool :: Value Bool

-- | Decoder of the <tt>INT2</tt> values.
int2 :: Value Int16

-- | Decoder of the <tt>INT4</tt> values.
int4 :: Value Int32

-- | Decoder of the <tt>INT8</tt> values.
int8 :: Value Int64

-- | Decoder of the <tt>FLOAT4</tt> values.
float4 :: Value Float

-- | Decoder of the <tt>FLOAT8</tt> values.
float8 :: Value Double

-- | Decoder of the <tt>NUMERIC</tt> values.
numeric :: Value Scientific

-- | Decoder of the <tt>CHAR</tt> values. Note that it supports UTF-8
--   values.
char :: Value Char

-- | Decoder of the <tt>TEXT</tt> values.
text :: Value Text

-- | Decoder of the <tt>BYTEA</tt> values.
bytea :: Value ByteString

-- | Decoder of the <tt>DATE</tt> values.
date :: Value Day

-- | Decoder of the <tt>TIMESTAMP</tt> values.
timestamp :: Value LocalTime

-- | Decoder of the <tt>TIMESTAMPTZ</tt> values.
--   
--   <i>NOTICE</i>
--   
--   Postgres does not store the timezone information of
--   <tt>TIMESTAMPTZ</tt>. Instead it stores a UTC value and performs
--   silent conversions to the currently set timezone, when dealt with in
--   the text format. However this library bypasses the silent conversions
--   and communicates with Postgres using the UTC values directly.
timestamptz :: Value UTCTime

-- | Decoder of the <tt>TIME</tt> values.
time :: Value TimeOfDay

-- | Decoder of the <tt>TIMETZ</tt> values.
--   
--   Unlike in case of <tt>TIMESTAMPTZ</tt>, Postgres does store the
--   timezone information for <tt>TIMETZ</tt>. However the Haskell's "time"
--   library does not contain any composite type, that fits the task, so we
--   use a pair of <a>TimeOfDay</a> and <a>TimeZone</a> to represent a
--   value on the Haskell's side.
timetz :: Value (TimeOfDay, TimeZone)

-- | Decoder of the <tt>INTERVAL</tt> values.
interval :: Value DiffTime

-- | Decoder of the <tt>UUID</tt> values.
uuid :: Value UUID

-- | Decoder of the <tt>JSON</tt> values into a JSON AST.
json :: Value Value

-- | Decoder of the <tt>JSON</tt> values into a raw JSON <a>ByteString</a>.
jsonBytes :: (ByteString -> Either Text a) -> Value a

-- | Decoder of the <tt>JSONB</tt> values into a JSON AST.
jsonb :: Value Value

-- | Decoder of the <tt>JSONB</tt> values into a raw JSON
--   <a>ByteString</a>.
jsonbBytes :: (ByteString -> Either Text a) -> Value a

-- | Lifts the <a>Array</a> decoder to the <a>Value</a> decoder.
array :: Array a -> Value a

-- | Lifts the <a>Composite</a> decoder to the <a>Value</a> decoder.
composite :: Composite a -> Value a

-- | A generic decoder of <tt>HSTORE</tt> values.
--   
--   Here's how you can use it to construct a specific value:
--   
--   <pre>
--   x :: Value [(Text, Maybe Text)]
--   x =
--     hstore <a>replicateM</a>
--   </pre>
hstore :: (forall m. Monad m => Int -> m (Text, Maybe Text) -> m a) -> Value a

-- | Given a partial mapping from text to value, produces a decoder of that
--   value.
enum :: (Text -> Maybe a) -> Value a

-- | Lifts a custom value decoder function to a <a>Value</a> decoder.
custom :: (Bool -> ByteString -> Either Text a) -> Value a

-- | A generic array decoder.
--   
--   Here's how you can use it to produce a specific array value decoder:
--   
--   <pre>
--   x :: Value [[Text]]
--   x =
--     array (arrayDimension <a>replicateM</a> (arrayDimension <a>replicateM</a> (arrayValue text)))
--   </pre>
data Array a

-- | A function for parsing a dimension of an array. Provides support for
--   multi-dimensional arrays.
--   
--   Accepts:
--   
--   <ul>
--   <li>An implementation of the <tt>replicateM</tt> function
--   (<tt>Control.Monad.<a>replicateM</a></tt>,
--   <tt>Data.Vector.<a>replicateM</a></tt>), which determines the output
--   value.</li>
--   <li>A decoder of its components, which can be either another
--   <a>arrayDimension</a>, <a>arrayValue</a> or
--   <a>arrayNullableValue</a>.</li>
--   </ul>
arrayDimension :: (forall m. Monad m => Int -> m a -> m b) -> Array a -> Array b

-- | Lift a <a>Value</a> decoder into an <a>Array</a> decoder for parsing
--   of non-nullable leaf values.
arrayValue :: Value a -> Array a

-- | Lift a <a>Value</a> decoder into an <a>Array</a> decoder for parsing
--   of nullable leaf values.
arrayNullableValue :: Value a -> Array (Maybe a)

-- | Composable decoder of composite values (rows, records).
data Composite a

-- | Lift a <a>Value</a> decoder into a <a>Composite</a> decoder for
--   parsing of non-nullable leaf values.
compositeValue :: Value a -> Composite a

-- | Lift a <a>Value</a> decoder into a <a>Composite</a> decoder for
--   parsing of nullable leaf values.
compositeNullableValue :: Value a -> Composite (Maybe a)
instance GHC.Base.Monad Hasql.Decoders.Composite
instance GHC.Base.Applicative Hasql.Decoders.Composite
instance GHC.Base.Functor Hasql.Decoders.Composite
instance GHC.Base.Functor Hasql.Decoders.Array
instance GHC.Base.Functor Hasql.Decoders.Value
instance GHC.Base.Monad Hasql.Decoders.Row
instance GHC.Base.Applicative Hasql.Decoders.Row
instance GHC.Base.Functor Hasql.Decoders.Row
instance GHC.Base.Functor Hasql.Decoders.Result
instance Data.Default.Class.Default (Hasql.Decoders.Result ())
instance Data.Default.Class.Default (Hasql.Decoders.Result GHC.Int.Int64)
instance Data.Default.Class.Default (Hasql.Decoders.Row a) => Data.Default.Class.Default (Hasql.Decoders.Result (GHC.Base.Maybe a))
instance Data.Default.Class.Default (Hasql.Decoders.Row a) => Data.Default.Class.Default (Hasql.Decoders.Result (Data.Vector.Vector a))
instance Data.Default.Class.Default (Hasql.Decoders.Row a) => Data.Default.Class.Default (Hasql.Decoders.Result [a])
instance Data.Default.Class.Default (Hasql.Decoders.Row a) => Data.Default.Class.Default (Hasql.Decoders.Result (Data.Functor.Identity.Identity a))
instance Data.Default.Class.Default (Hasql.Decoders.Value a) => Data.Default.Class.Default (Hasql.Decoders.Row (Data.Functor.Identity.Identity a))
instance Data.Default.Class.Default (Hasql.Decoders.Value a) => Data.Default.Class.Default (Hasql.Decoders.Row (GHC.Base.Maybe a))
instance (Data.Default.Class.Default (Hasql.Decoders.Value a1), Data.Default.Class.Default (Hasql.Decoders.Value a2)) => Data.Default.Class.Default (Hasql.Decoders.Row (a1, a2))
instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Types.Bool)
instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Int.Int16)
instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Int.Int32)
instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Int.Int64)
instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Types.Float)
instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Types.Double)
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Scientific.Scientific)
instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Types.Char)
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Text.Internal.Text)
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.ByteString.Internal.ByteString)
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.Calendar.Days.Day)
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.LocalTime.LocalTime.LocalTime)
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.Clock.UTC.UTCTime)
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.LocalTime.TimeOfDay.TimeOfDay)
instance Data.Default.Class.Default (Hasql.Decoders.Value (Data.Time.LocalTime.TimeOfDay.TimeOfDay, Data.Time.LocalTime.TimeZone.TimeZone))
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.Clock.Scale.DiffTime)
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.UUID.Types.Internal.UUID)
instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Aeson.Types.Internal.Value)

module Hasql.Query

-- | An abstraction over parametric queries.
--   
--   It is composable using the standard interfaces of the category theory,
--   which it has instances of. E.g., here's how you can compose queries
--   using the Arrow notation:
--   
--   <pre>
--   -- |
--   -- Given an Update query,
--   -- which uses the @fmap (&gt; 0) <a>rowsAffected</a>@ decoder
--   -- to detect, whether it had any effect,
--   -- and an Insert query,
--   -- produces a query which performs Upsert.
--   composeUpsert :: Query a Bool -&gt; Query a () -&gt; Query a ()
--   composeUpsert update insert =
--     proc params -&gt; do
--       updated &lt;- update -&lt; params
--       if updated
--         then <a>returnA</a> -&lt; ()
--         else insert -&lt; params
--   </pre>
data Query a b

-- | A specification of a strictly single-statement query, which can be
--   parameterized and prepared.
--   
--   Consists of the following:
--   
--   <ul>
--   <li>SQL template,</li>
--   <li>params encoder,</li>
--   <li>result decoder,</li>
--   <li>a flag, determining whether it should be prepared.</li>
--   </ul>
--   
--   The SQL template must be formatted according to Postgres' standard,
--   with any non-ASCII characters of the template encoded using UTF-8.
--   According to the format, parameters must be referred to using the
--   positional notation, as in the following: <tt>$1</tt>, <tt>$2</tt>,
--   <tt>$3</tt> and etc. Those references must be used to refer to the
--   values of the <a>Params</a> encoder.
--   
--   Following is an example of the declaration of a prepared statement
--   with its associated codecs.
--   
--   <pre>
--   selectSum :: Hasql.Query.<a>Query</a> (Int64, Int64) Int64
--   selectSum =
--     Hasql.Query.<a>statement</a> sql encoder decoder True
--     where
--       sql =
--         "select ($1 + $2)"
--       encoder =
--         <a>contramap</a> <a>fst</a> (Hasql.Private.Encoders.<a>value</a> Hasql.Private.Encoders.<a>int8</a>) <a>&lt;&gt;</a>
--         <a>contramap</a> <a>snd</a> (Hasql.Private.Encoders.<a>value</a> Hasql.Private.Encoders.<a>int8</a>)
--       decoder =
--         Hasql.Private.Decoders.<a>singleRow</a> (Hasql.Private.Decoders.<a>value</a> Hasql.Private.Decoders.<a>int8</a>)
--   </pre>
--   
--   The statement above accepts a product of two parameters of type
--   <a>Int64</a> and produces a single result of type <a>Int64</a>.
statement :: ByteString -> Params a -> Result b -> Bool -> Query a b
