    {-# LANGUAGE ConstraintKinds            #-}
    {-# LANGUAGE DataKinds                  #-}
    {-# LANGUAGE DefaultSignatures          #-}
    {-# LANGUAGE DeriveGeneric              #-}
    {-# LANGUAGE FlexibleContexts           #-}
    {-# LANGUAGE FlexibleInstances          #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE KindSignatures             #-}
    {-# LANGUAGE MultiParamTypeClasses      #-}
    {-# LANGUAGE OverloadedStrings          #-}
    {-# LANGUAGE PolyKinds                  #-}
    {-# LANGUAGE ScopedTypeVariables        #-}
    {-# LANGUAGE TypeFamilies               #-}
    {-# LANGUAGE TypeOperators              #-}
    {-# LANGUAGE UndecidableInstances       #-}
    module Web.Internal.FormUrlEncoded where

    import           Control.Applicative        (Const(Const))
    import           Control.Arrow              ((***))
    import           Control.Monad              ((<=<))
    import           Data.ByteString.Builder    (shortByteString, toLazyByteString)
    import qualified Data.ByteString.Lazy       as BSL
    import qualified Data.ByteString.Lazy.Char8 as BSL8
    import           Data.Coerce                (coerce)
    import qualified Data.Foldable              as F
    import           Data.Functor.Identity      (Identity(Identity))
    import           Data.Hashable              (Hashable)
    import           Data.HashMap.Strict        (HashMap)
    import qualified Data.HashMap.Strict        as HashMap
    import           Data.Int                   (Int16, Int32, Int64, Int8)
    import           Data.IntMap                (IntMap)
    import qualified Data.IntMap                as IntMap
    import           Data.List                  (intersperse, sortBy)
    import           Data.Map                   (Map)
    import qualified Data.Map                   as Map
    import           Data.Monoid                (All (..), Any (..), Dual (..),
                                                 Product (..), Sum (..))
    import           Data.Ord                   (comparing)
    import           Data.Proxy                 (Proxy (..))
    import           Data.Semigroup             (Semigroup (..))
    import qualified Data.Semigroup             as Semi
    import           Data.Tagged                (Tagged (..))
    import           Data.Text                  (Text)
    import qualified Data.Text                  as Text
    import qualified Data.Text.Encoding         as Text
    import           Data.Text.Encoding.Error   (lenientDecode)
    import qualified Data.Text.Lazy             as Lazy
    import           Data.Time.Compat           (Day, LocalTime, NominalDiffTime,
                                                 UTCTime, ZonedTime)
    import           Data.Time.Calendar.Month.Compat (Month)
    import           Data.Time.Calendar.Quarter.Compat (Quarter, QuarterOfYear (..))
    import           Data.Void                  (Void)
    import           Data.Word                  (Word16, Word32, Word64, Word8)
    import           GHC.Exts                   (Constraint, IsList (..))
    import           GHC.Generics
    import           GHC.TypeLits
    import           Network.HTTP.Types.URI     (urlDecode, urlEncodeBuilder)
    import           Numeric.Natural            (Natural)
    import           Web.Internal.HttpApiData

    -- $setup
    -- >>> :set -XDeriveGeneric -XOverloadedLists -XOverloadedStrings -XFlexibleContexts -XScopedTypeVariables -XTypeFamilies
    -- >>> import GHC.Generics (Generic)
    -- >>> import Data.Char (toLower)
    -- >>> import Data.Text (Text)
    -- >>> import Data.Word (Word8)
    --
    -- >>> data Person = Person { name :: String, age :: Int } deriving (Show, Generic)
    -- >>> instance ToForm Person
    -- >>> instance FromForm Person
    --
    -- >>> data Post = Post { title :: String, subtitle :: Maybe String, comments :: [String]} deriving (Generic, Show)
    -- >>> instance ToForm Post
    -- >>> instance FromForm Post
    --
    -- >>> data Project = Project { projectName :: String, projectSize :: Int } deriving (Generic, Show)
    -- >>> let myOptions = FormOptions { fieldLabelModifier = map toLower . drop (length ("project" :: String)) }
    -- >>> instance ToForm Project where toForm = genericToForm myOptions
    -- >>> instance FromForm Project where fromForm = genericFromForm myOptions

    -- | Typeclass for types that can be used as keys in a 'Form'-like container (like 'Map').
    class ToFormKey k where
      -- | Render a key for a 'Form'.
      toFormKey :: k -> Text

    instance ToFormKey ()       where toFormKey :: () -> Text
    toFormKey = () -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Char     where toFormKey :: Char -> Text
    toFormKey = Char -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam

    instance ToFormKey Bool     where toFormKey :: Bool -> Text
    toFormKey = Bool -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Ordering where toFormKey :: Ordering -> Text
    toFormKey = Ordering -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam

    instance ToFormKey Double   where toFormKey :: Double -> Text
    toFormKey = Double -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Float    where toFormKey :: Float -> Text
    toFormKey = Float -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Int      where toFormKey :: Int -> Text
    toFormKey = Int -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Int8     where toFormKey :: Int8 -> Text
    toFormKey = Int8 -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Int16    where toFormKey :: Int16 -> Text
    toFormKey = Int16 -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Int32    where toFormKey :: Int32 -> Text
    toFormKey = Int32 -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Int64    where toFormKey :: Int64 -> Text
    toFormKey = Int64 -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Integer  where toFormKey :: Integer -> Text
    toFormKey = Integer -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Word     where toFormKey :: Word -> Text
    toFormKey = Word -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Word8    where toFormKey :: Word8 -> Text
    toFormKey = Word8 -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Word16   where toFormKey :: Word16 -> Text
    toFormKey = Word16 -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Word32   where toFormKey :: Word32 -> Text
    toFormKey = Word32 -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Word64   where toFormKey :: Word64 -> Text
    toFormKey = Word64 -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam

    instance ToFormKey Day              where toFormKey :: Day -> Text
    toFormKey = Day -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey LocalTime        where toFormKey :: LocalTime -> Text
    toFormKey = LocalTime -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey ZonedTime        where toFormKey :: ZonedTime -> Text
    toFormKey = ZonedTime -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey UTCTime          where toFormKey :: UTCTime -> Text
    toFormKey = UTCTime -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey NominalDiffTime  where toFormKey :: NominalDiffTime -> Text
    toFormKey = NominalDiffTime -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Quarter          where toFormKey :: Quarter -> Text
    toFormKey = Quarter -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey QuarterOfYear    where toFormKey :: QuarterOfYear -> Text
    toFormKey = QuarterOfYear -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Month            where toFormKey :: Month -> Text
    toFormKey = Month -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam

    instance ToFormKey String     where toFormKey :: String -> Text
    toFormKey = String -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Text       where toFormKey :: Text -> Text
    toFormKey = Text -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Lazy.Text  where toFormKey :: Text -> Text
    toFormKey = Text -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam

    instance ToFormKey All where toFormKey :: All -> Text
    toFormKey = All -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Any where toFormKey :: Any -> Text
    toFormKey = Any -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam

    instance ToFormKey a => ToFormKey (Dual a)    where toFormKey :: Dual a -> Text
    toFormKey = (a -> Text) -> Dual a -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)
    instance ToFormKey a => ToFormKey (Sum a)     where toFormKey :: Sum a -> Text
    toFormKey = (a -> Text) -> Sum a -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)
    instance ToFormKey a => ToFormKey (Product a) where toFormKey :: Product a -> Text
    toFormKey = (a -> Text) -> Product a -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)

    instance ToFormKey a => ToFormKey (Semi.Min a)   where toFormKey :: Min a -> Text
    toFormKey = (a -> Text) -> Min a -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)
    instance ToFormKey a => ToFormKey (Semi.Max a)   where toFormKey :: Max a -> Text
    toFormKey = (a -> Text) -> Max a -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)
    instance ToFormKey a => ToFormKey (Semi.First a) where toFormKey :: First a -> Text
    toFormKey = (a -> Text) -> First a -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)
    instance ToFormKey a => ToFormKey (Semi.Last a)  where toFormKey :: Last a -> Text
    toFormKey = (a -> Text) -> Last a -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)

    instance ToFormKey a => ToFormKey (Tagged b a)  where toFormKey :: Tagged b a -> Text
    toFormKey = (a -> Text) -> Tagged b a -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)

    -- | @since 0.4.2
    instance ToFormKey a => ToFormKey (Identity a)   where toFormKey :: Identity a -> Text
    toFormKey = (a -> Text) -> Identity a -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)

    -- | @since 0.4.2
    instance ToFormKey a => ToFormKey (Const a b) where
        toFormKey :: Const a b -> Text
    toFormKey = (a -> Text) -> Const a b -> Text
    forall a b. Coercible a b => a -> b
    coerce (a -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey :: a -> Text)

    instance ToFormKey Void     where toFormKey :: Void -> Text
    toFormKey = Void -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam
    instance ToFormKey Natural  where toFormKey :: Natural -> Text
    toFormKey = Natural -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam

    -- | Typeclass for types that can be parsed from keys of a 'Form'. This is the reverse of 'ToFormKey'.
    class FromFormKey k where
      -- | Parse a key of a 'Form'.
      parseFormKey :: Text -> Either Text k

    instance FromFormKey ()       where parseFormKey :: Text -> Either Text ()
    parseFormKey = Text -> Either Text ()
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Char     where parseFormKey :: Text -> Either Text Char
    parseFormKey = Text -> Either Text Char
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam

    instance FromFormKey Bool     where parseFormKey :: Text -> Either Text Bool
    parseFormKey = Text -> Either Text Bool
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Ordering where parseFormKey :: Text -> Either Text Ordering
    parseFormKey = Text -> Either Text Ordering
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam

    instance FromFormKey Double   where parseFormKey :: Text -> Either Text Double
    parseFormKey = Text -> Either Text Double
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Float    where parseFormKey :: Text -> Either Text Float
    parseFormKey = Text -> Either Text Float
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Int      where parseFormKey :: Text -> Either Text Int
    parseFormKey = Text -> Either Text Int
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Int8     where parseFormKey :: Text -> Either Text Int8
    parseFormKey = Text -> Either Text Int8
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Int16    where parseFormKey :: Text -> Either Text Int16
    parseFormKey = Text -> Either Text Int16
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Int32    where parseFormKey :: Text -> Either Text Int32
    parseFormKey = Text -> Either Text Int32
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Int64    where parseFormKey :: Text -> Either Text Int64
    parseFormKey = Text -> Either Text Int64
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Integer  where parseFormKey :: Text -> Either Text Integer
    parseFormKey = Text -> Either Text Integer
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Word     where parseFormKey :: Text -> Either Text Word
    parseFormKey = Text -> Either Text Word
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Word8    where parseFormKey :: Text -> Either Text Word8
    parseFormKey = Text -> Either Text Word8
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Word16   where parseFormKey :: Text -> Either Text Word16
    parseFormKey = Text -> Either Text Word16
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Word32   where parseFormKey :: Text -> Either Text Word32
    parseFormKey = Text -> Either Text Word32
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Word64   where parseFormKey :: Text -> Either Text Word64
    parseFormKey = Text -> Either Text Word64
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam

    instance FromFormKey Day              where parseFormKey :: Text -> Either Text Day
    parseFormKey = Text -> Either Text Day
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey LocalTime        where parseFormKey :: Text -> Either Text LocalTime
    parseFormKey = Text -> Either Text LocalTime
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey ZonedTime        where parseFormKey :: Text -> Either Text ZonedTime
    parseFormKey = Text -> Either Text ZonedTime
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey UTCTime          where parseFormKey :: Text -> Either Text UTCTime
    parseFormKey = Text -> Either Text UTCTime
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey NominalDiffTime  where parseFormKey :: Text -> Either Text NominalDiffTime
    parseFormKey = Text -> Either Text NominalDiffTime
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Quarter          where parseFormKey :: Text -> Either Text Quarter
    parseFormKey = Text -> Either Text Quarter
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey QuarterOfYear    where parseFormKey :: Text -> Either Text QuarterOfYear
    parseFormKey = Text -> Either Text QuarterOfYear
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Month            where parseFormKey :: Text -> Either Text Month
    parseFormKey = Text -> Either Text Month
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam

    instance FromFormKey String     where parseFormKey :: Text -> Either Text String
    parseFormKey = Text -> Either Text String
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Text       where parseFormKey :: Text -> Either Text Text
    parseFormKey = Text -> Either Text Text
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Lazy.Text  where parseFormKey :: Text -> Either Text Text
    parseFormKey = Text -> Either Text Text
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam

    instance FromFormKey All where parseFormKey :: Text -> Either Text All
    parseFormKey = Text -> Either Text All
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Any where parseFormKey :: Text -> Either Text Any
    parseFormKey = Text -> Either Text Any
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam

    instance FromFormKey a => FromFormKey (Dual a)    where parseFormKey :: Text -> Either Text (Dual a)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (Dual a)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)
    instance FromFormKey a => FromFormKey (Sum a)     where parseFormKey :: Text -> Either Text (Sum a)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (Sum a)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)
    instance FromFormKey a => FromFormKey (Product a) where parseFormKey :: Text -> Either Text (Product a)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (Product a)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)

    instance FromFormKey a => FromFormKey (Semi.Min a)   where parseFormKey :: Text -> Either Text (Min a)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (Min a)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)
    instance FromFormKey a => FromFormKey (Semi.Max a)   where parseFormKey :: Text -> Either Text (Max a)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (Max a)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)
    instance FromFormKey a => FromFormKey (Semi.First a) where parseFormKey :: Text -> Either Text (First a)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (First a)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)
    instance FromFormKey a => FromFormKey (Semi.Last a)  where parseFormKey :: Text -> Either Text (Last a)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (Last a)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)

    instance FromFormKey a => FromFormKey (Tagged b a) where parseFormKey :: Text -> Either Text (Tagged b a)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (Tagged b a)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)

    -- | @since 0.4.2
    instance FromFormKey a => FromFormKey (Identity a) where parseFormKey :: Text -> Either Text (Identity a)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (Identity a)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)

    -- | @since 0.4.2
    instance FromFormKey a => FromFormKey (Const a b) where
        parseFormKey :: Text -> Either Text (Const a b)
    parseFormKey = (Text -> Either Text a) -> Text -> Either Text (Const a b)
    forall a b. Coercible a b => a -> b
    coerce (Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey :: Text -> Either Text a)

    instance FromFormKey Void     where parseFormKey :: Text -> Either Text Void
    parseFormKey = Text -> Either Text Void
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam
    instance FromFormKey Natural  where parseFormKey :: Text -> Either Text Natural
    parseFormKey = Text -> Either Text Natural
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam

    -- | The contents of a form, not yet URL-encoded.
    --
    -- 'Form' can be URL-encoded with 'urlEncodeForm' and URL-decoded with 'urlDecodeForm'.
    newtype Form = Form { Form -> HashMap Text [Text]
    unForm :: HashMap Text [Text] }
      deriving (Form -> Form -> Bool
    (Form -> Form -> Bool) -> (Form -> Form -> Bool) -> Eq Form
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Form -> Form -> Bool
    == :: Form -> Form -> Bool
    $c/= :: Form -> Form -> Bool
    /= :: Form -> Form -> Bool
    Eq, ReadPrec [Form]
    ReadPrec Form
    Int -> ReadS Form
    ReadS [Form]
    (Int -> ReadS Form)
    -> ReadS [Form] -> ReadPrec Form -> ReadPrec [Form] -> Read Form
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS Form
    readsPrec :: Int -> ReadS Form
    $creadList :: ReadS [Form]
    readList :: ReadS [Form]
    $creadPrec :: ReadPrec Form
    readPrec :: ReadPrec Form
    $creadListPrec :: ReadPrec [Form]
    readListPrec :: ReadPrec [Form]
    Read, (forall x. Form -> Rep Form x)
    -> (forall x. Rep Form x -> Form) -> Generic Form
    forall x. Rep Form x -> Form
    forall x. Form -> Rep Form x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. Form -> Rep Form x
    from :: forall x. Form -> Rep Form x
    $cto :: forall x. Rep Form x -> Form
    to :: forall x. Rep Form x -> Form
    Generic, NonEmpty Form -> Form
    Form -> Form -> Form
    (Form -> Form -> Form)
    -> (NonEmpty Form -> Form)
    -> (forall b. Integral b => b -> Form -> Form)
    -> Semigroup Form
    forall b. Integral b => b -> Form -> Form
    forall a.
    (a -> a -> a)
    -> (NonEmpty a -> a)
    -> (forall b. Integral b => b -> a -> a)
    -> Semigroup a
    $c<> :: Form -> Form -> Form
    <> :: Form -> Form -> Form
    $csconcat :: NonEmpty Form -> Form
    sconcat :: NonEmpty Form -> Form
    $cstimes :: forall b. Integral b => b -> Form -> Form
    stimes :: forall b. Integral b => b -> Form -> Form
    Semigroup, Semigroup Form
    Form
    Semigroup Form =>
    Form -> (Form -> Form -> Form) -> ([Form] -> Form) -> Monoid Form
    [Form] -> Form
    Form -> Form -> Form
    forall a.
    Semigroup a =>
    a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
    $cmempty :: Form
    mempty :: Form
    $cmappend :: Form -> Form -> Form
    mappend :: Form -> Form -> Form
    $cmconcat :: [Form] -> Form
    mconcat :: [Form] -> Form
    Monoid)

    instance Show Form where
      showsPrec :: Int -> Form -> ShowS
    showsPrec Int
    d Form
    form = Bool -> ShowS -> ShowS
    showParen (Int
    d Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    10) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $
        String -> ShowS
    showString String
    "fromList " ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [(Text, Text)] -> ShowS
    forall a. Show a => a -> ShowS
    shows (Form -> [(Text, Text)]
    toListStable Form
    form)

    -- | _NOTE:_ 'toList' is unstable and may result in different key order (but not values).
    -- For a stable conversion use 'toListStable'.
    instance IsList Form where
      type Item Form = (Text, Text)
      fromList :: [Item Form] -> Form
    fromList = HashMap Text [Text] -> Form
    Form (HashMap Text [Text] -> Form)
    -> ([(Text, Text)] -> HashMap Text [Text])
    -> [(Text, Text)]
    -> Form
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Text] -> [Text] -> [Text])
    -> [(Text, [Text])] -> HashMap Text [Text]
    forall k v.
    (Eq k, Hashable k) =>
    (v -> v -> v) -> [(k, v)] -> HashMap k v
    HashMap.fromListWith (([Text] -> [Text] -> [Text]) -> [Text] -> [Text] -> [Text]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip [Text] -> [Text] -> [Text]
    forall a. Semigroup a => a -> a -> a
    (<>)) ([(Text, [Text])] -> HashMap Text [Text])
    -> ([(Text, Text)] -> [(Text, [Text])])
    -> [(Text, Text)]
    -> HashMap Text [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Text, Text) -> (Text, [Text]))
    -> [(Text, Text)] -> [(Text, [Text])]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\(Text
    k, Text
    v) -> (Text
    k, [Text
    v]))
      toList :: Form -> [Item Form]
    toList = ((Text, [Text]) -> [(Text, Text)])
    -> [(Text, [Text])] -> [(Text, Text)]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (\(Text
    k, [Text]
    vs) -> (Text -> (Text, Text)) -> [Text] -> [(Text, Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map ((,) Text
    k) [Text]
    vs) ([(Text, [Text])] -> [(Text, Text)])
    -> (Form -> [(Text, [Text])]) -> Form -> [(Text, Text)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . HashMap Text [Text] -> [(Text, [Text])]
    forall k v. HashMap k v -> [(k, v)]
    HashMap.toList (HashMap Text [Text] -> [(Text, [Text])])
    -> (Form -> HashMap Text [Text]) -> Form -> [(Text, [Text])]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> HashMap Text [Text]
    unForm

    -- | A stable version of 'toList'.
    toListStable :: Form -> [(Text, Text)]
    toListStable :: Form -> [(Text, Text)]
    toListStable = ((Text, Text) -> Text) -> [(Text, Text)] -> [(Text, Text)]
    forall b a. Ord b => (a -> b) -> [a] -> [a]
    sortOn (Text, Text) -> Text
    forall a b. (a, b) -> a
    fst ([(Text, Text)] -> [(Text, Text)])
    -> (Form -> [(Text, Text)]) -> Form -> [(Text, Text)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> [(Text, Text)]
    Form -> [Item Form]
    forall l. IsList l => l -> [Item l]
    toList

    -- | Convert a value into 'Form'.
    --
    -- An example type and instance:
    --
    -- @
    -- {-\# LANGUAGE OverloadedLists \#-}
    --
    -- data Person = Person
    --   { name :: String
    --   , age  :: Int }
    --
    -- instance 'ToForm' Person where
    --   'toForm' person =
    --     [ (\"name\", 'toQueryParam' (name person))
    --     , (\"age\", 'toQueryParam' (age person)) ]
    -- @
    --
    -- Instead of manually writing @'ToForm'@ instances you can
    -- use a default generic implementation of @'toForm'@.
    --
    -- To do that, simply add @deriving 'Generic'@ clause to your datatype
    -- and declare a 'ToForm' instance for your datatype without
    -- giving definition for 'toForm'.
    --
    -- For instance, the previous example can be simplified into this:
    --
    -- @
    -- data Person = Person
    --   { name :: String
    --   , age  :: Int
    --   } deriving ('Generic')
    --
    -- instance 'ToForm' Person
    -- @
    --
    -- The default implementation of 'toForm' is 'genericToForm'.
    class ToForm a where
      -- | Convert a value into 'Form'.
      toForm :: a -> Form
      default toForm :: (Generic a, GToForm a (Rep a)) => a -> Form
      toForm = FormOptions -> a -> Form
    forall a.
    (Generic a, GToForm a (Rep a)) =>
    FormOptions -> a -> Form
    genericToForm FormOptions
    defaultFormOptions

    instance ToForm Form where toForm :: Form -> Form
    toForm = Form -> Form
    forall a. a -> a
    id

    instance (ToFormKey k, ToHttpApiData v) => ToForm [(k, v)] where
      toForm :: [(k, v)] -> Form
    toForm = [(Text, Text)] -> Form
    [Item Form] -> Form
    forall l. IsList l => [Item l] -> l
    fromList ([(Text, Text)] -> Form)
    -> ([(k, v)] -> [(Text, Text)]) -> [(k, v)] -> Form
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((k, v) -> (Text, Text)) -> [(k, v)] -> [(Text, Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map (k -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey (k -> Text) -> (v -> Text) -> (k, v) -> (Text, Text)
    forall b c b' c'. (b -> c) -> (b' -> c') -> (b, b') -> (c, c')
    forall (a :: * -> * -> *) b c b' c'.
    Arrow a =>
    a b c -> a b' c' -> a (b, b') (c, c')
    *** v -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam)

    instance (ToFormKey k, ToHttpApiData v) => ToForm (Map k [v]) where
      toForm :: Map k [v] -> Form
    toForm = [(k, [v])] -> Form
    forall k v. (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form
    fromEntriesByKey ([(k, [v])] -> Form)
    -> (Map k [v] -> [(k, [v])]) -> Map k [v] -> Form
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Map k [v] -> [(k, [v])]
    forall k a. Map k a -> [(k, a)]
    Map.toList

    instance (ToFormKey k, ToHttpApiData v) => ToForm (HashMap k [v]) where
      toForm :: HashMap k [v] -> Form
    toForm = [(k, [v])] -> Form
    forall k v. (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form
    fromEntriesByKey ([(k, [v])] -> Form)
    -> (HashMap k [v] -> [(k, [v])]) -> HashMap k [v] -> Form
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . HashMap k [v] -> [(k, [v])]
    forall k v. HashMap k v -> [(k, v)]
    HashMap.toList

    instance ToHttpApiData v => ToForm (IntMap [v]) where
      toForm :: IntMap [v] -> Form
    toForm = [(Int, [v])] -> Form
    forall k v. (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form
    fromEntriesByKey ([(Int, [v])] -> Form)
    -> (IntMap [v] -> [(Int, [v])]) -> IntMap [v] -> Form
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IntMap [v] -> [(Int, [v])]
    forall a. IntMap a -> [(Int, a)]
    IntMap.toList

    -- | Convert a list of entries groupped by key into a 'Form'.
    --
    -- >>> fromEntriesByKey [("name",["Nick"]),("color",["red","blue"])]
    -- fromList [("color","red"),("color","blue"),("name","Nick")]
    fromEntriesByKey :: (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form
    fromEntriesByKey :: forall k v. (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form
    fromEntriesByKey = HashMap Text [Text] -> Form
    Form (HashMap Text [Text] -> Form)
    -> ([(k, [v])] -> HashMap Text [Text]) -> [(k, [v])] -> Form
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Text] -> [Text] -> [Text])
    -> [(Text, [Text])] -> HashMap Text [Text]
    forall k v.
    (Eq k, Hashable k) =>
    (v -> v -> v) -> [(k, v)] -> HashMap k v
    HashMap.fromListWith [Text] -> [Text] -> [Text]
    forall a. Semigroup a => a -> a -> a
    (<>) ([(Text, [Text])] -> HashMap Text [Text])
    -> ([(k, [v])] -> [(Text, [Text])])
    -> [(k, [v])]
    -> HashMap Text [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((k, [v]) -> (Text, [Text])) -> [(k, [v])] -> [(Text, [Text])]
    forall a b. (a -> b) -> [a] -> [b]
    map (k -> Text
    forall k. ToFormKey k => k -> Text
    toFormKey (k -> Text) -> ([v] -> [Text]) -> (k, [v]) -> (Text, [Text])
    forall b c b' c'. (b -> c) -> (b' -> c') -> (b, b') -> (c, c')
    forall (a :: * -> * -> *) b c b' c'.
    Arrow a =>
    a b c -> a b' c' -> a (b, b') (c, c')
    *** (v -> Text) -> [v] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map v -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam)

    data Proxy3 a b c = Proxy3

    type family NotSupported (cls :: k1) (a :: k2) (reason :: Symbol) :: Constraint where
      NotSupported cls a reason = TypeError
        ( 'Text "Cannot derive a Generic-based " ':<>: 'ShowType cls ':<>: 'Text " instance for " ':<>: 'ShowType a ':<>: 'Text "." ':$$:
          'ShowType a ':<>: 'Text " " ':<>: 'Text reason ':<>: 'Text "," ':$$:
          'Text "but Generic-based " ':<>: 'ShowType cls ':<>: 'Text " instances can be derived only for records" ':$$:
          'Text "(i.e. product types with named fields)." )

    -- | A 'Generic'-based implementation of 'toForm'.
    -- This is used as a default implementation in 'ToForm'.
    --
    -- Note that this only works for records (i.e. product data types with named fields):
    --
    -- @
    -- data Person = Person
    --   { name :: String
    --   , age  :: Int
    --   } deriving ('Generic')
    -- @
    --
    -- In this implementation each field's value gets encoded using `toQueryParam`.
    -- Two field types are exceptions:
    --
    --    - for values of type @'Maybe' a@ an entry is added to the 'Form' only when it is @'Just' x@
    --      and the encoded value is @'toQueryParam' x@; 'Nothing' values are omitted from the 'Form';
    --
    --    - for values of type @[a]@ (except @['Char']@) an entry is added for every item in the list;
    --      if the list is empty no entries are added to the 'Form';
    --
    -- Here's an example:
    --
    -- @
    -- data Post = Post
    --   { title    :: String
    --   , subtitle :: Maybe String
    --   , comments :: [String]
    --   } deriving ('Generic', 'Show')
    --
    -- instance 'ToForm' Post
    -- @
    --
    -- >>> urlEncodeAsFormStable Post { title = "Test", subtitle = Nothing, comments = ["Nice post!", "+1"] }
    -- "comments=Nice%20post%21&comments=%2B1&title=Test"
    genericToForm :: forall a. (Generic a, GToForm a (Rep a)) => FormOptions -> a -> Form
    genericToForm :: forall a.
    (Generic a, GToForm a (Rep a)) =>
    FormOptions -> a -> Form
    genericToForm FormOptions
    opts = Proxy a -> FormOptions -> Rep a (ZonkAny 1) -> Form
    forall x. Proxy a -> FormOptions -> Rep a x -> Form
    forall {k} (t :: k) (f :: * -> *) x.
    GToForm t f =>
    Proxy t -> FormOptions -> f x -> Form
    gToForm (Proxy a
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy a) FormOptions
    opts (Rep a (ZonkAny 1) -> Form)
    -> (a -> Rep a (ZonkAny 1)) -> a -> Form
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Rep a (ZonkAny 1)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from

    class GToForm t (f :: * -> *) where
      gToForm :: Proxy t -> FormOptions -> f x -> Form

    instance (GToForm t f, GToForm t g) => GToForm t (f :*: g) where
      gToForm :: forall x. Proxy t -> FormOptions -> (:*:) f g x -> Form
    gToForm Proxy t
    p FormOptions
    opts (f x
    a :*: g x
    b) = Proxy t -> FormOptions -> f x -> Form
    forall x. Proxy t -> FormOptions -> f x -> Form
    forall {k} (t :: k) (f :: * -> *) x.
    GToForm t f =>
    Proxy t -> FormOptions -> f x -> Form
    gToForm Proxy t
    p FormOptions
    opts f x
    a Form -> Form -> Form
    forall a. Semigroup a => a -> a -> a
    <> Proxy t -> FormOptions -> g x -> Form
    forall x. Proxy t -> FormOptions -> g x -> Form
    forall {k} (t :: k) (f :: * -> *) x.
    GToForm t f =>
    Proxy t -> FormOptions -> f x -> Form
    gToForm Proxy t
    p FormOptions
    opts g x
    b

    instance (GToForm t f) => GToForm t (M1 D x f) where
      gToForm :: forall x. Proxy t -> FormOptions -> M1 D x f x -> Form
    gToForm Proxy t
    p FormOptions
    opts (M1 f x
    a) = Proxy t -> FormOptions -> f x -> Form
    forall x. Proxy t -> FormOptions -> f x -> Form
    forall {k} (t :: k) (f :: * -> *) x.
    GToForm t f =>
    Proxy t -> FormOptions -> f x -> Form
    gToForm Proxy t
    p FormOptions
    opts f x
    a

    instance (GToForm t f) => GToForm t (M1 C x f) where
      gToForm :: forall x. Proxy t -> FormOptions -> M1 C x f x -> Form
    gToForm Proxy t
    p FormOptions
    opts (M1 f x
    a) = Proxy t -> FormOptions -> f x -> Form
    forall x. Proxy t -> FormOptions -> f x -> Form
    forall {k} (t :: k) (f :: * -> *) x.
    GToForm t f =>
    Proxy t -> FormOptions -> f x -> Form
    gToForm Proxy t
    p FormOptions
    opts f x
    a

    instance {-# OVERLAPPABLE #-} (Selector s, ToHttpApiData c) => GToForm t (M1 S s (K1 i c)) where
      gToForm :: forall x. Proxy t -> FormOptions -> M1 S s (K1 i c) x -> Form
    gToForm Proxy t
    _ FormOptions
    opts (M1 (K1 c
    c)) = [Item Form] -> Form
    forall l. IsList l => [Item l] -> l
    fromList [(Text
    key, c -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam c
    c)]
        where
          key :: Text
    key = String -> Text
    Text.pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ FormOptions -> ShowS
    fieldLabelModifier FormOptions
    opts ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Proxy3 s (ZonkAny 13) (ZonkAny 12) -> String
    forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
           (f :: k1 -> *) (a :: k1).
    Selector s =>
    t s f a -> String
    forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
           (a :: k1).
    t s f a -> String
    selName (Proxy3 s g p
    forall {k} {k} {g :: k} {p :: k}. Proxy3 s g p
    forall {k} {k} {k} (a :: k) (b :: k) (c :: k). Proxy3 a b c
    Proxy3 :: Proxy3 s g p)

    instance (Selector s, ToHttpApiData c) => GToForm t (M1 S s (K1 i (Maybe c))) where
      gToForm :: forall x.
    Proxy t -> FormOptions -> M1 S s (K1 i (Maybe c)) x -> Form
    gToForm Proxy t
    _ FormOptions
    opts (M1 (K1 Maybe c
    c)) =
        case Maybe c
    c of
          Maybe c
    Nothing -> Form
    forall a. Monoid a => a
    mempty
          Just c
    x  -> [Item Form] -> Form
    forall l. IsList l => [Item l] -> l
    fromList [(Text
    key, c -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam c
    x)]
        where
          key :: Text
    key = String -> Text
    Text.pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ FormOptions -> ShowS
    fieldLabelModifier FormOptions
    opts ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Proxy3 s (ZonkAny 10) (ZonkAny 9) -> String
    forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
           (f :: k1 -> *) (a :: k1).
    Selector s =>
    t s f a -> String
    forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
           (a :: k1).
    t s f a -> String
    selName (Proxy3 s g p
    forall {k} {k} {g :: k} {p :: k}. Proxy3 s g p
    forall {k} {k} {k} (a :: k) (b :: k) (c :: k). Proxy3 a b c
    Proxy3 :: Proxy3 s g p)

    instance (Selector s, ToHttpApiData c) => GToForm t (M1 S s (K1 i [c])) where
      gToForm :: forall x. Proxy t -> FormOptions -> M1 S s (K1 i [c]) x -> Form
    gToForm Proxy t
    _ FormOptions
    opts (M1 (K1 [c]
    cs)) = [Item Form] -> Form
    forall l. IsList l => [Item l] -> l
    fromList ((c -> (Text, Text)) -> [c] -> [(Text, Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\c
    c -> (Text
    key, c -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam c
    c)) [c]
    cs)
        where
          key :: Text
    key = String -> Text
    Text.pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ FormOptions -> ShowS
    fieldLabelModifier FormOptions
    opts ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Proxy3 s (ZonkAny 7) (ZonkAny 6) -> String
    forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
           (f :: k1 -> *) (a :: k1).
    Selector s =>
    t s f a -> String
    forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
           (a :: k1).
    t s f a -> String
    selName (Proxy3 s g p
    forall {k} {k} {g :: k} {p :: k}. Proxy3 s g p
    forall {k} {k} {k} (a :: k) (b :: k) (c :: k). Proxy3 a b c
    Proxy3 :: Proxy3 s g p)

    instance {-# OVERLAPPING #-} (Selector s) => GToForm t (M1 S s (K1 i String)) where
      gToForm :: forall x. Proxy t -> FormOptions -> M1 S s (K1 i String) x -> Form
    gToForm Proxy t
    _ FormOptions
    opts (M1 (K1 String
    c)) = [Item Form] -> Form
    forall l. IsList l => [Item l] -> l
    fromList [(Text
    key, String -> Text
    forall a. ToHttpApiData a => a -> Text
    toQueryParam String
    c)]
        where
          key :: Text
    key = String -> Text
    Text.pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ FormOptions -> ShowS
    fieldLabelModifier FormOptions
    opts ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Proxy3 s (ZonkAny 4) (ZonkAny 3) -> String
    forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
           (f :: k1 -> *) (a :: k1).
    Selector s =>
    t s f a -> String
    forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
           (a :: k1).
    t s f a -> String
    selName (Proxy3 s g p
    forall {k} {k} {g :: k} {p :: k}. Proxy3 s g p
    forall {k} {k} {k} (a :: k) (b :: k) (c :: k). Proxy3 a b c
    Proxy3 :: Proxy3 s g p)

    instance NotSupported ToForm t "is a sum type" => GToForm t (f :+: g) where gToForm :: forall x. Proxy t -> FormOptions -> (:+:) f g x -> Form
    gToForm = String -> Proxy t -> FormOptions -> (:+:) f g x -> Form
    forall a. HasCallStack => String -> a
    error String
    "impossible"

    -- | Parse 'Form' into a value.
    --
    -- An example type and instance:
    --
    -- @
    -- data Person = Person
    --   { name :: String
    --   , age  :: Int }
    --
    -- instance 'FromForm' Person where
    --   'fromForm' f = Person
    --     '<$>' 'parseUnique' "name" f
    --     '<*>' 'parseUnique' "age"  f
    -- @
    --
    -- Instead of manually writing @'FromForm'@ instances you can
    -- use a default generic implementation of @'fromForm'@.
    --
    -- To do that, simply add @deriving 'Generic'@ clause to your datatype
    -- and declare a 'FromForm' instance for your datatype without
    -- giving definition for 'fromForm'.
    --
    -- For instance, the previous example can be simplified into this:
    --
    -- @
    -- data Person = Person
    --   { name :: String
    --   , age  :: Int
    --   } deriving ('Generic')
    --
    -- instance 'FromForm' Person
    -- @
    --
    -- The default implementation of 'fromForm' is 'genericFromForm'.
    -- It only works for records and it will use 'parseQueryParam' for each field's value.
    class FromForm a where
      -- | Parse 'Form' into a value.
      fromForm :: Form -> Either Text a
      default fromForm :: (Generic a, GFromForm a (Rep a)) => Form -> Either Text a
      fromForm = FormOptions -> Form -> Either Text a
    forall a.
    (Generic a, GFromForm a (Rep a)) =>
    FormOptions -> Form -> Either Text a
    genericFromForm FormOptions
    defaultFormOptions

    instance FromForm Form where fromForm :: Form -> Either Text Form
    fromForm = Form -> Either Text Form
    forall a. a -> Either Text a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure

    -- | _NOTE:_ this conversion is unstable and may result in different key order (but not values).
    instance (FromFormKey k, FromHttpApiData v) => FromForm [(k, v)] where
      fromForm :: Form -> Either Text [(k, v)]
    fromForm = ([(k, [v])] -> [(k, v)])
    -> Either Text [(k, [v])] -> Either Text [(k, v)]
    forall a b. (a -> b) -> Either Text a -> Either Text b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (((k, [v]) -> [(k, v)]) -> [(k, [v])] -> [(k, v)]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (\(k
    k, [v]
    vs) -> (v -> (k, v)) -> [v] -> [(k, v)]
    forall a b. (a -> b) -> [a] -> [b]
    map ((,) k
    k) [v]
    vs)) (Either Text [(k, [v])] -> Either Text [(k, v)])
    -> (Form -> Either Text [(k, [v])]) -> Form -> Either Text [(k, v)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> Either Text [(k, [v])]
    forall k v.
    (FromFormKey k, FromHttpApiData v) =>
    Form -> Either Text [(k, [v])]
    toEntriesByKey

    instance (Ord k, FromFormKey k, FromHttpApiData v) => FromForm (Map k [v]) where
      fromForm :: Form -> Either Text (Map k [v])
    fromForm = ([(k, [v])] -> Map k [v])
    -> Either Text [(k, [v])] -> Either Text (Map k [v])
    forall a b. (a -> b) -> Either Text a -> Either Text b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([v] -> [v] -> [v]) -> [(k, [v])] -> Map k [v]
    forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
    Map.fromListWith [v] -> [v] -> [v]
    forall a. Semigroup a => a -> a -> a
    (<>)) (Either Text [(k, [v])] -> Either Text (Map k [v]))
    -> (Form -> Either Text [(k, [v])])
    -> Form
    -> Either Text (Map k [v])
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> Either Text [(k, [v])]
    forall k v.
    (FromFormKey k, FromHttpApiData v) =>
    Form -> Either Text [(k, [v])]
    toEntriesByKey

    instance (Eq k, Hashable k, FromFormKey k, FromHttpApiData v) => FromForm (HashMap k [v]) where
      fromForm :: Form -> Either Text (HashMap k [v])
    fromForm = ([(k, [v])] -> HashMap k [v])
    -> Either Text [(k, [v])] -> Either Text (HashMap k [v])
    forall a b. (a -> b) -> Either Text a -> Either Text b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([v] -> [v] -> [v]) -> [(k, [v])] -> HashMap k [v]
    forall k v.
    (Eq k, Hashable k) =>
    (v -> v -> v) -> [(k, v)] -> HashMap k v
    HashMap.fromListWith [v] -> [v] -> [v]
    forall a. Semigroup a => a -> a -> a
    (<>)) (Either Text [(k, [v])] -> Either Text (HashMap k [v]))
    -> (Form -> Either Text [(k, [v])])
    -> Form
    -> Either Text (HashMap k [v])
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> Either Text [(k, [v])]
    forall k v.
    (FromFormKey k, FromHttpApiData v) =>
    Form -> Either Text [(k, [v])]
    toEntriesByKey

    instance FromHttpApiData v => FromForm (IntMap [v]) where
      fromForm :: Form -> Either Text (IntMap [v])
    fromForm = ([(Int, [v])] -> IntMap [v])
    -> Either Text [(Int, [v])] -> Either Text (IntMap [v])
    forall a b. (a -> b) -> Either Text a -> Either Text b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([v] -> [v] -> [v]) -> [(Int, [v])] -> IntMap [v]
    forall a. (a -> a -> a) -> [(Int, a)] -> IntMap a
    IntMap.fromListWith [v] -> [v] -> [v]
    forall a. Semigroup a => a -> a -> a
    (<>)) (Either Text [(Int, [v])] -> Either Text (IntMap [v]))
    -> (Form -> Either Text [(Int, [v])])
    -> Form
    -> Either Text (IntMap [v])
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> Either Text [(Int, [v])]
    forall k v.
    (FromFormKey k, FromHttpApiData v) =>
    Form -> Either Text [(k, [v])]
    toEntriesByKey

    -- | Parse a 'Form' into a list of entries groupped by key.
    --
    -- _NOTE:_ this conversion is unstable and may result in different key order
    -- (but not values). For a stable encoding see 'toEntriesByKeyStable'.
    toEntriesByKey :: (FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])]
    toEntriesByKey :: forall k v.
    (FromFormKey k, FromHttpApiData v) =>
    Form -> Either Text [(k, [v])]
    toEntriesByKey = ((Text, [Text]) -> Either Text (k, [v]))
    -> [(Text, [Text])] -> Either Text [(k, [v])]
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> [a] -> f [b]
    traverse (Text, [Text]) -> Either Text (k, [v])
    forall {a} {t :: * -> *} {b}.
    (FromFormKey a, Traversable t, FromHttpApiData b) =>
    (Text, t Text) -> Either Text (a, t b)
    parseGroup ([(Text, [Text])] -> Either Text [(k, [v])])
    -> (Form -> [(Text, [Text])]) -> Form -> Either Text [(k, [v])]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . HashMap Text [Text] -> [(Text, [Text])]
    forall k v. HashMap k v -> [(k, v)]
    HashMap.toList (HashMap Text [Text] -> [(Text, [Text])])
    -> (Form -> HashMap Text [Text]) -> Form -> [(Text, [Text])]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> HashMap Text [Text]
    unForm
      where
        parseGroup :: (Text, t Text) -> Either Text (a, t b)
    parseGroup (Text
    k, t Text
    vs) = (,) (a -> t b -> (a, t b))
    -> Either Text a -> Either Text (t b -> (a, t b))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> Either Text a
    forall k. FromFormKey k => Text -> Either Text k
    parseFormKey Text
    k Either Text (t b -> (a, t b))
    -> Either Text (t b) -> Either Text (a, t b)
    forall a b. Either Text (a -> b) -> Either Text a -> Either Text b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> (Text -> Either Text b) -> t Text -> Either Text (t b)
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b)
    traverse Text -> Either Text b
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam t Text
    vs

    -- | Parse a 'Form' into a list of entries groupped by key.
    --
    -- >>> toEntriesByKeyStable [("name", "Nick"), ("color", "red"), ("color", "white")] :: Either Text [(Text, [Text])]
    -- Right [("color",["red","white"]),("name",["Nick"])]
    --
    -- For an unstable (but faster) conversion see 'toEntriesByKey'.
    toEntriesByKeyStable :: (Ord k, FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])]
    toEntriesByKeyStable :: forall k v.
    (Ord k, FromFormKey k, FromHttpApiData v) =>
    Form -> Either Text [(k, [v])]
    toEntriesByKeyStable = ([(k, [v])] -> [(k, [v])])
    -> Either Text [(k, [v])] -> Either Text [(k, [v])]
    forall a b. (a -> b) -> Either Text a -> Either Text b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (((k, [v]) -> k) -> [(k, [v])] -> [(k, [v])]
    forall b a. Ord b => (a -> b) -> [a] -> [a]
    sortOn (k, [v]) -> k
    forall a b. (a, b) -> a
    fst) (Either Text [(k, [v])] -> Either Text [(k, [v])])
    -> (Form -> Either Text [(k, [v])])
    -> Form
    -> Either Text [(k, [v])]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> Either Text [(k, [v])]
    forall k v.
    (FromFormKey k, FromHttpApiData v) =>
    Form -> Either Text [(k, [v])]
    toEntriesByKey

    -- | A 'Generic'-based implementation of 'fromForm'.
    -- This is used as a default implementation in 'FromForm'.
    --
    -- Note that this only works for records (i.e. product data types with named fields):
    --
    -- @
    -- data Person = Person
    --   { name :: String
    --   , age  :: Int
    --   } deriving ('Generic')
    -- @
    --
    -- In this implementation each field's value gets decoded using `parseQueryParam`.
    -- Two field types are exceptions:
    --
    --    - for values of type @'Maybe' a@ an entry is parsed if present in the 'Form'
    --      and the is decoded with 'parseQueryParam'; if no entry is present result is 'Nothing';
    --
    --    - for values of type @[a]@ (except @['Char']@) all entries are parsed to produce a list of parsed values;
    --
    -- Here's an example:
    --
    -- @
    -- data Post = Post
    --   { title    :: String
    --   , subtitle :: Maybe String
    --   , comments :: [String]
    --   } deriving ('Generic', 'Show')
    --
    -- instance 'FromForm' Post
    -- @
    --
    -- >>> urlDecodeAsForm "comments=Nice%20post%21&comments=%2B1&title=Test" :: Either Text Post
    -- Right (Post {title = "Test", subtitle = Nothing, comments = ["Nice post!","+1"]})
    genericFromForm :: forall a. (Generic a, GFromForm a (Rep a)) => FormOptions -> Form -> Either Text a
    genericFromForm :: forall a.
    (Generic a, GFromForm a (Rep a)) =>
    FormOptions -> Form -> Either Text a
    genericFromForm FormOptions
    opts Form
    f = Rep a (ZonkAny 0) -> a
    forall a x. Generic a => Rep a x -> a
    forall x. Rep a x -> a
    to (Rep a (ZonkAny 0) -> a)
    -> Either Text (Rep a (ZonkAny 0)) -> Either Text a
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy a -> FormOptions -> Form -> Either Text (Rep a (ZonkAny 0))
    forall x. Proxy a -> FormOptions -> Form -> Either Text (Rep a x)
    forall {k} (t :: k) (f :: * -> *) x.
    GFromForm t f =>
    Proxy t -> FormOptions -> Form -> Either Text (f x)
    gFromForm (Proxy a
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy a) FormOptions
    opts Form
    f

    class GFromForm t (f :: * -> *) where
      gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (f x)

    instance (GFromForm t f, GFromForm t g) => GFromForm t (f :*: g) where
      gFromForm :: forall x.
    Proxy t -> FormOptions -> Form -> Either Text ((:*:) f g x)
    gFromForm Proxy t
    p FormOptions
    opts Form
    f = f x -> g x -> (:*:) f g x
    forall k (f :: k -> *) (g :: k -> *) (p :: k).
    f p -> g p -> (:*:) f g p
    (:*:) (f x -> g x -> (:*:) f g x)
    -> Either Text (f x) -> Either Text (g x -> (:*:) f g x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy t -> FormOptions -> Form -> Either Text (f x)
    forall x. Proxy t -> FormOptions -> Form -> Either Text (f x)
    forall {k} (t :: k) (f :: * -> *) x.
    GFromForm t f =>
    Proxy t -> FormOptions -> Form -> Either Text (f x)
    gFromForm Proxy t
    p FormOptions
    opts Form
    f Either Text (g x -> (:*:) f g x)
    -> Either Text (g x) -> Either Text ((:*:) f g x)
    forall a b. Either Text (a -> b) -> Either Text a -> Either Text b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Proxy t -> FormOptions -> Form -> Either Text (g x)
    forall x. Proxy t -> FormOptions -> Form -> Either Text (g x)
    forall {k} (t :: k) (f :: * -> *) x.
    GFromForm t f =>
    Proxy t -> FormOptions -> Form -> Either Text (f x)
    gFromForm Proxy t
    p FormOptions
    opts Form
    f

    instance GFromForm t f => GFromForm t (M1 D x f) where
      gFromForm :: forall x.
    Proxy t -> FormOptions -> Form -> Either Text (M1 D x f x)
    gFromForm Proxy t
    p FormOptions
    opts Form
    f = f x -> M1 D x f x
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1 (f x -> M1 D x f x)
    -> Either Text (f x) -> Either Text (M1 D x f x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy t -> FormOptions -> Form -> Either Text (f x)
    forall x. Proxy t -> FormOptions -> Form -> Either Text (f x)
    forall {k} (t :: k) (f :: * -> *) x.
    GFromForm t f =>
    Proxy t -> FormOptions -> Form -> Either Text (f x)
    gFromForm Proxy t
    p FormOptions
    opts Form
    f

    instance GFromForm t f => GFromForm t (M1 C x f) where
      gFromForm :: forall x.
    Proxy t -> FormOptions -> Form -> Either Text (M1 C x f x)
    gFromForm Proxy t
    p FormOptions
    opts Form
    f = f x -> M1 C x f x
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1 (f x -> M1 C x f x)
    -> Either Text (f x) -> Either Text (M1 C x f x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy t -> FormOptions -> Form -> Either Text (f x)
    forall x. Proxy t -> FormOptions -> Form -> Either Text (f x)
    forall {k} (t :: k) (f :: * -> *) x.
    GFromForm t f =>
    Proxy t -> FormOptions -> Form -> Either Text (f x)
    gFromForm Proxy t
    p FormOptions
    opts Form
    f

    instance {-# OVERLAPPABLE #-} (Selector s, FromHttpApiData c) => GFromForm t (M1 S s (K1 i c)) where
      gFromForm :: forall x.
    Proxy t -> FormOptions -> Form -> Either Text (M1 S s (K1 i c) x)
    gFromForm Proxy t
    _ FormOptions
    opts Form
    form = K1 i c x -> M1 S s (K1 i c) x
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1 (K1 i c x -> M1 S s (K1 i c) x)
    -> (c -> K1 i c x) -> c -> M1 S s (K1 i c) x
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . c -> K1 i c x
    forall k i c (p :: k). c -> K1 i c p
    K1 (c -> M1 S s (K1 i c) x)
    -> Either Text c -> Either Text (M1 S s (K1 i c) x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> Form -> Either Text c
    forall v. FromHttpApiData v => Text -> Form -> Either Text v
    parseUnique Text
    key Form
    form
        where
          key :: Text
    key = String -> Text
    Text.pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ FormOptions -> ShowS
    fieldLabelModifier FormOptions
    opts ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Proxy3 s (ZonkAny 25) (ZonkAny 24) -> String
    forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
           (f :: k1 -> *) (a :: k1).
    Selector s =>
    t s f a -> String
    forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
           (a :: k1).
    t s f a -> String
    selName (Proxy3 s g p
    forall {k} {k} {g :: k} {p :: k}. Proxy3 s g p
    forall {k} {k} {k} (a :: k) (b :: k) (c :: k). Proxy3 a b c
    Proxy3 :: Proxy3 s g p)

    instance (Selector s, FromHttpApiData c) => GFromForm t (M1 S s (K1 i (Maybe c))) where
      gFromForm :: forall x.
    Proxy t
    -> FormOptions -> Form -> Either Text (M1 S s (K1 i (Maybe c)) x)
    gFromForm Proxy t
    _ FormOptions
    opts Form
    form = K1 i (Maybe c) x -> M1 S s (K1 i (Maybe c)) x
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1 (K1 i (Maybe c) x -> M1 S s (K1 i (Maybe c)) x)
    -> (Maybe c -> K1 i (Maybe c) x)
    -> Maybe c
    -> M1 S s (K1 i (Maybe c)) x
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Maybe c -> K1 i (Maybe c) x
    forall k i c (p :: k). c -> K1 i c p
    K1 (Maybe c -> M1 S s (K1 i (Maybe c)) x)
    -> Either Text (Maybe c) -> Either Text (M1 S s (K1 i (Maybe c)) x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> Form -> Either Text (Maybe c)
    forall v.
    FromHttpApiData v =>
    Text -> Form -> Either Text (Maybe v)
    parseMaybe Text
    key Form
    form
        where
          key :: Text
    key = String -> Text
    Text.pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ FormOptions -> ShowS
    fieldLabelModifier FormOptions
    opts ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Proxy3 s (ZonkAny 22) (ZonkAny 21) -> String
    forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
           (f :: k1 -> *) (a :: k1).
    Selector s =>
    t s f a -> String
    forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
           (a :: k1).
    t s f a -> String
    selName (Proxy3 s g p
    forall {k} {k} {g :: k} {p :: k}. Proxy3 s g p
    forall {k} {k} {k} (a :: k) (b :: k) (c :: k). Proxy3 a b c
    Proxy3 :: Proxy3 s g p)

    instance (Selector s, FromHttpApiData c) => GFromForm t (M1 S s (K1 i [c])) where
      gFromForm :: forall x.
    Proxy t -> FormOptions -> Form -> Either Text (M1 S s (K1 i [c]) x)
    gFromForm Proxy t
    _ FormOptions
    opts Form
    form = K1 i [c] x -> M1 S s (K1 i [c]) x
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1 (K1 i [c] x -> M1 S s (K1 i [c]) x)
    -> ([c] -> K1 i [c] x) -> [c] -> M1 S s (K1 i [c]) x
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [c] -> K1 i [c] x
    forall k i c (p :: k). c -> K1 i c p
    K1 ([c] -> M1 S s (K1 i [c]) x)
    -> Either Text [c] -> Either Text (M1 S s (K1 i [c]) x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> Form -> Either Text [c]
    forall v. FromHttpApiData v => Text -> Form -> Either Text [v]
    parseAll Text
    key Form
    form
        where
          key :: Text
    key = String -> Text
    Text.pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ FormOptions -> ShowS
    fieldLabelModifier FormOptions
    opts ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Proxy3 s (ZonkAny 19) (ZonkAny 18) -> String
    forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
           (f :: k1 -> *) (a :: k1).
    Selector s =>
    t s f a -> String
    forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
           (a :: k1).
    t s f a -> String
    selName (Proxy3 s g p
    forall {k} {k} {g :: k} {p :: k}. Proxy3 s g p
    forall {k} {k} {k} (a :: k) (b :: k) (c :: k). Proxy3 a b c
    Proxy3 :: Proxy3 s g p)

    instance {-# OVERLAPPING #-} (Selector s) => GFromForm t (M1 S s (K1 i String)) where
      gFromForm :: forall x.
    Proxy t
    -> FormOptions -> Form -> Either Text (M1 S s (K1 i String) x)
    gFromForm Proxy t
    _ FormOptions
    opts Form
    form = K1 i String x -> M1 S s (K1 i String) x
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1 (K1 i String x -> M1 S s (K1 i String) x)
    -> (String -> K1 i String x) -> String -> M1 S s (K1 i String) x
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> K1 i String x
    forall k i c (p :: k). c -> K1 i c p
    K1 (String -> M1 S s (K1 i String) x)
    -> Either Text String -> Either Text (M1 S s (K1 i String) x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> Form -> Either Text String
    forall v. FromHttpApiData v => Text -> Form -> Either Text v
    parseUnique Text
    key Form
    form
        where
          key :: Text
    key = String -> Text
    Text.pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ FormOptions -> ShowS
    fieldLabelModifier FormOptions
    opts ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Proxy3 s (ZonkAny 16) (ZonkAny 15) -> String
    forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
           (f :: k1 -> *) (a :: k1).
    Selector s =>
    t s f a -> String
    forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
           (a :: k1).
    t s f a -> String
    selName (Proxy3 s g p
    forall {k} {k} {g :: k} {p :: k}. Proxy3 s g p
    forall {k} {k} {k} (a :: k) (b :: k) (c :: k). Proxy3 a b c
    Proxy3 :: Proxy3 s g p)

    instance NotSupported FromForm t "is a sum type" => GFromForm t (f :+: g) where gFromForm :: forall x.
    Proxy t -> FormOptions -> Form -> Either Text ((:+:) f g x)
    gFromForm = String
    -> Proxy t -> FormOptions -> Form -> Either Text ((:+:) f g x)
    forall a. HasCallStack => String -> a
    error String
    "impossible"

    -- | Encode a 'Form' to an @application/x-www-form-urlencoded@ 'BSL.ByteString'.
    --
    -- _NOTE:_ this encoding is unstable and may result in different key order
    -- (but not values). For a stable encoding see 'urlEncodeFormStable'.
    urlEncodeForm :: Form -> BSL.ByteString
    urlEncodeForm :: Form -> ByteString
    urlEncodeForm = [(Text, Text)] -> ByteString
    urlEncodeParams ([(Text, Text)] -> ByteString)
    -> (Form -> [(Text, Text)]) -> Form -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> [(Text, Text)]
    Form -> [Item Form]
    forall l. IsList l => l -> [Item l]
    toList

    -- | Encode a 'Form' to an @application/x-www-form-urlencoded@ 'BSL.ByteString'.
    --
    -- For an unstable (but faster) encoding see 'urlEncodeForm'.
    --
    -- Key-value pairs get encoded to @key=value@ and separated by @&@:
    --
    -- >>> urlEncodeFormStable [("name", "Julian"), ("lastname", "Arni")]
    -- "lastname=Arni&name=Julian"
    --
    -- Keys with empty values get encoded to just @key@ (without the @=@ sign):
    --
    -- >>> urlEncodeFormStable [("is_test", "")]
    -- "is_test"
    --
    -- Empty keys are allowed too:
    --
    -- >>> urlEncodeFormStable [("", "foobar")]
    -- "=foobar"
    --
    -- However, if both key and value are empty, the key-value pair is ignored.
    -- (This prevents @'urlDecodeForm' . 'urlEncodeFormStable'@ from being a true isomorphism).
    --
    -- >>> urlEncodeFormStable [("", "")]
    -- ""
    --
    -- Everything is escaped with @'escapeURIString' 'isUnreserved'@:
    --
    -- >>> urlEncodeFormStable [("fullname", "Andres Löh")]
    -- "fullname=Andres%20L%C3%B6h"
    urlEncodeFormStable :: Form -> BSL.ByteString
    urlEncodeFormStable :: Form -> ByteString
    urlEncodeFormStable = [(Text, Text)] -> ByteString
    urlEncodeParams ([(Text, Text)] -> ByteString)
    -> (Form -> [(Text, Text)]) -> Form -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Text, Text) -> Text) -> [(Text, Text)] -> [(Text, Text)]
    forall b a. Ord b => (a -> b) -> [a] -> [a]
    sortOn (Text, Text) -> Text
    forall a b. (a, b) -> a
    fst ([(Text, Text)] -> [(Text, Text)])
    -> (Form -> [(Text, Text)]) -> Form -> [(Text, Text)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> [(Text, Text)]
    Form -> [Item Form]
    forall l. IsList l => l -> [Item l]
    toList

    -- | Encode a list of key-value pairs to an @application/x-www-form-urlencoded@ 'BSL.ByteString'.
    --
    -- See also 'urlEncodeFormStable'.
    urlEncodeParams :: [(Text, Text)] -> BSL.ByteString
    urlEncodeParams :: [(Text, Text)] -> ByteString
    urlEncodeParams = Builder -> ByteString
    toLazyByteString (Builder -> ByteString)
    -> ([(Text, Text)] -> Builder) -> [(Text, Text)] -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Builder] -> Builder
    forall a. Monoid a => [a] -> a
    mconcat ([Builder] -> Builder)
    -> ([(Text, Text)] -> [Builder]) -> [(Text, Text)] -> Builder
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> [Builder] -> [Builder]
    forall a. a -> [a] -> [a]
    intersperse (ShortByteString -> Builder
    shortByteString ShortByteString
    "&") ([Builder] -> [Builder])
    -> ([(Text, Text)] -> [Builder]) -> [(Text, Text)] -> [Builder]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Text, Text) -> Builder) -> [(Text, Text)] -> [Builder]
    forall a b. (a -> b) -> [a] -> [b]
    map (Text, Text) -> Builder
    encodePair
      where
        escape :: Text -> Builder
    escape = Bool -> ByteString -> Builder
    urlEncodeBuilder Bool
    True (ByteString -> Builder) -> (Text -> ByteString) -> Text -> Builder
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> ByteString
    Text.encodeUtf8

        encodePair :: (Text, Text) -> Builder
    encodePair (Text
    k, Text
    "") = Text -> Builder
    escape Text
    k
        encodePair (Text
    k, Text
    v)  = Text -> Builder
    escape Text
    k Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> ShortByteString -> Builder
    shortByteString ShortByteString
    "=" Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Text -> Builder
    escape Text
    v

    -- | Decode an @application/x-www-form-urlencoded@ 'BSL.ByteString' to a 'Form'.
    --
    -- Key-value pairs get decoded normally:
    --
    -- >>> urlDecodeForm "name=Greg&lastname=Weber"
    -- Right (fromList [("lastname","Weber"),("name","Greg")])
    --
    -- Keys with no values get decoded to pairs with empty values.
    --
    -- >>> urlDecodeForm "is_test"
    -- Right (fromList [("is_test","")])
    --
    -- Empty keys are allowed:
    --
    -- >>> urlDecodeForm "=foobar"
    -- Right (fromList [("","foobar")])
    --
    -- The empty string gets decoded into an empty 'Form':
    --
    -- >>> urlDecodeForm ""
    -- Right (fromList [])
    --
    -- Everything is un-escaped with 'unEscapeString':
    --
    -- >>> urlDecodeForm "fullname=Andres%20L%C3%B6h"
    -- Right (fromList [("fullname","Andres L\246h")])
    --
    -- Improperly formed strings result in an error:
    --
    -- >>> urlDecodeForm "this=has=too=many=equals"
    -- Left "not a valid pair: this=has=too=many=equals"
    urlDecodeForm :: BSL.ByteString -> Either Text Form
    urlDecodeForm :: ByteString -> Either Text Form
    urlDecodeForm = ([(Text, Text)] -> Form)
    -> Either Text [(Text, Text)] -> Either Text Form
    forall a b. (a -> b) -> Either Text a -> Either Text b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap [(Text, Text)] -> Form
    forall a. ToForm a => a -> Form
    toForm (Either Text [(Text, Text)] -> Either Text Form)
    -> (ByteString -> Either Text [(Text, Text)])
    -> ByteString
    -> Either Text Form
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Either Text [(Text, Text)]
    urlDecodeParams

    -- | Decode an @application/x-www-form-urlencoded@ 'BSL.ByteString' to a list of key-value pairs.
    --
    -- See also 'urlDecodeForm'.
    urlDecodeParams :: BSL.ByteString -> Either Text [(Text, Text)]
    urlDecodeParams :: ByteString -> Either Text [(Text, Text)]
    urlDecodeParams ByteString
    bs = ([ByteString] -> Either Text (Text, Text))
    -> [[ByteString]] -> Either Text [(Text, Text)]
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> [a] -> f [b]
    traverse [ByteString] -> Either Text (Text, Text)
    parsePair [[ByteString]]
    pairs
      where
        pairs :: [[ByteString]]
    pairs = (ByteString -> [ByteString]) -> [ByteString] -> [[ByteString]]
    forall a b. (a -> b) -> [a] -> [b]
    map (Char -> ByteString -> [ByteString]
    BSL8.split Char
    '=') (Char -> ByteString -> [ByteString]
    BSL8.split Char
    '&' ByteString
    bs)

        unescape :: ByteString -> Text
    unescape = OnDecodeError -> ByteString -> Text
    Text.decodeUtf8With OnDecodeError
    lenientDecode (ByteString -> Text)
    -> (ByteString -> ByteString) -> ByteString -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Bool -> ByteString -> ByteString
    urlDecode Bool
    True (ByteString -> ByteString)
    -> (ByteString -> ByteString) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> ByteString
    BSL.toStrict

        parsePair :: [ByteString] -> Either Text (Text, Text)
    parsePair [ByteString]
    p =
          case (ByteString -> Text) -> [ByteString] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map ByteString -> Text
    unescape [ByteString]
    p of
            [Text
    k, Text
    v] -> (Text, Text) -> Either Text (Text, Text)
    forall a. a -> Either Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text
    k, Text
    v)
            [Text
    k]    -> (Text, Text) -> Either Text (Text, Text)
    forall a. a -> Either Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text
    k, Text
    "")
            [Text]
    xs     -> Text -> Either Text (Text, Text)
    forall a b. a -> Either a b
    Left (Text -> Either Text (Text, Text))
    -> Text -> Either Text (Text, Text)
    forall a b. (a -> b) -> a -> b
    $ Text
    "not a valid pair: " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> [Text] -> Text
    Text.intercalate Text
    "=" [Text]
    xs

    -- | This is a convenience function for decoding a
    -- @application/x-www-form-urlencoded@ 'BSL.ByteString' directly to a datatype
    -- that has an instance of 'FromForm'.
    --
    -- This is effectively @'fromForm' '<=<' 'urlDecodeForm'@.
    --
    -- >>> urlDecodeAsForm "name=Dennis&age=22" :: Either Text Person
    -- Right (Person {name = "Dennis", age = 22})
    urlDecodeAsForm :: FromForm a => BSL.ByteString -> Either Text a
    urlDecodeAsForm :: forall a. FromForm a => ByteString -> Either Text a
    urlDecodeAsForm = Form -> Either Text a
    forall a. FromForm a => Form -> Either Text a
    fromForm (Form -> Either Text a)
    -> (ByteString -> Either Text Form) -> ByteString -> Either Text a
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< ByteString -> Either Text Form
    urlDecodeForm

    -- | This is a convenience function for encoding a datatype that has instance
    -- of 'ToForm' directly to a @application/x-www-form-urlencoded@
    -- 'BSL.ByteString'.
    --
    -- This is effectively @'urlEncodeForm' . 'toForm'@.
    --
    -- _NOTE:_ this encoding is unstable and may result in different key order
    -- (but not values). For a stable encoding see 'urlEncodeAsFormStable'.
    urlEncodeAsForm :: ToForm a => a -> BSL.ByteString
    urlEncodeAsForm :: forall a. ToForm a => a -> ByteString
    urlEncodeAsForm = Form -> ByteString
    urlEncodeForm (Form -> ByteString) -> (a -> Form) -> a -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Form
    forall a. ToForm a => a -> Form
    toForm

    -- | This is a convenience function for encoding a datatype that has instance
    -- of 'ToForm' directly to a @application/x-www-form-urlencoded@
    -- 'BSL.ByteString'.
    --
    -- This is effectively @'urlEncodeFormStable' . 'toForm'@.
    --
    -- >>> urlEncodeAsFormStable Person {name = "Dennis", age = 22}
    -- "age=22&name=Dennis"
    urlEncodeAsFormStable :: ToForm a => a -> BSL.ByteString
    urlEncodeAsFormStable :: forall a. ToForm a => a -> ByteString
    urlEncodeAsFormStable = Form -> ByteString
    urlEncodeFormStable (Form -> ByteString) -> (a -> Form) -> a -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Form
    forall a. ToForm a => a -> Form
    toForm

    -- | Find all values corresponding to a given key in a 'Form'.
    --
    -- >>> lookupAll "name" []
    -- []
    -- >>> lookupAll "name" [("name", "Oleg")]
    -- ["Oleg"]
    -- >>> lookupAll "name" [("name", "Oleg"), ("name", "David")]
    -- ["Oleg","David"]
    lookupAll :: Text -> Form -> [Text]
    lookupAll :: Text -> Form -> [Text]
    lookupAll Text
    key = Maybe [Text] -> [Text]
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    F.concat (Maybe [Text] -> [Text])
    -> (Form -> Maybe [Text]) -> Form -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> HashMap Text [Text] -> Maybe [Text]
    forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
    HashMap.lookup Text
    key (HashMap Text [Text] -> Maybe [Text])
    -> (Form -> HashMap Text [Text]) -> Form -> Maybe [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Form -> HashMap Text [Text]
    unForm

    -- | Lookup an optional value for a key.
    -- Fail if there is more than one value.
    --
    -- >>> lookupMaybe "name" []
    -- Right Nothing
    -- >>> lookupMaybe "name" [("name", "Oleg")]
    -- Right (Just "Oleg")
    -- >>> lookupMaybe "name" [("name", "Oleg"), ("name", "David")]
    -- Left "Duplicate key \"name\""
    lookupMaybe :: Text -> Form -> Either Text (Maybe Text)
    lookupMaybe :: Text -> Form -> Either Text (Maybe Text)
    lookupMaybe Text
    key Form
    form =
      case Text -> Form -> [Text]
    lookupAll Text
    key Form
    form of
        []  -> Maybe Text -> Either Text (Maybe Text)
    forall a. a -> Either Text a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe Text
    forall a. Maybe a
    Nothing
        [Text
    v] -> Maybe Text -> Either Text (Maybe Text)
    forall a. a -> Either Text a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Text -> Maybe Text
    forall a. a -> Maybe a
    Just Text
    v)
        [Text]
    _   -> Text -> Either Text (Maybe Text)
    forall a b. a -> Either a b
    Left (Text -> Either Text (Maybe Text))
    -> Text -> Either Text (Maybe Text)
    forall a b. (a -> b) -> a -> b
    $ Text
    "Duplicate key " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> String -> Text
    Text.pack (Text -> String
    forall a. Show a => a -> String
    show Text
    key)

    -- | Lookup a unique value for a key.
    -- Fail if there is zero or more than one value.
    --
    -- >>> lookupUnique "name" []
    -- Left "Could not find key \"name\""
    -- >>> lookupUnique "name" [("name", "Oleg")]
    -- Right "Oleg"
    -- >>> lookupUnique "name" [("name", "Oleg"), ("name", "David")]
    -- Left "Duplicate key \"name\""
    lookupUnique :: Text -> Form -> Either Text Text
    lookupUnique :: Text -> Form -> Either Text Text
    lookupUnique Text
    key Form
    form = do
      mv <- Text -> Form -> Either Text (Maybe Text)
    lookupMaybe Text
    key Form
    form
      case mv of
        Just Text
    v  -> Text -> Either Text Text
    forall a. a -> Either Text a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Text
    v
        Maybe Text
    Nothing -> Text -> Either Text Text
    forall a b. a -> Either a b
    Left (Text -> Either Text Text) -> Text -> Either Text Text
    forall a b. (a -> b) -> a -> b
    $ Text
    "Could not find key " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> String -> Text
    Text.pack (Text -> String
    forall a. Show a => a -> String
    show Text
    key)

    -- | Lookup all values for a given key in a 'Form' and parse them with 'parseQueryParams'.
    --
    -- >>> parseAll "age" [] :: Either Text [Word8]
    -- Right []
    -- >>> parseAll "age" [("age", "8"), ("age", "seven")] :: Either Text [Word8]
    -- Left "could not parse: `seven' (input does not start with a digit)"
    -- >>> parseAll "age" [("age", "8"), ("age", "777")] :: Either Text [Word8]
    -- Left "out of bounds: `777' (should be between 0 and 255)"
    -- >>> parseAll "age" [("age", "12"), ("age", "25")] :: Either Text [Word8]
    -- Right [12,25]
    parseAll :: FromHttpApiData v => Text -> Form -> Either Text [v]
    parseAll :: forall v. FromHttpApiData v => Text -> Form -> Either Text [v]
    parseAll Text
    key = [Text] -> Either Text [v]
    forall (t :: * -> *) a.
    (Traversable t, FromHttpApiData a) =>
    t Text -> Either Text (t a)
    parseQueryParams ([Text] -> Either Text [v])
    -> (Form -> [Text]) -> Form -> Either Text [v]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Form -> [Text]
    lookupAll Text
    key

    -- | Lookup an optional value for a given key and parse it with 'parseQueryParam'.
    -- Fail if there is more than one value for the key.
    --
    -- >>> parseMaybe "age" [] :: Either Text (Maybe Word8)
    -- Right Nothing
    -- >>> parseMaybe "age" [("age", "12"), ("age", "25")] :: Either Text (Maybe Word8)
    -- Left "Duplicate key \"age\""
    -- >>> parseMaybe "age" [("age", "seven")] :: Either Text (Maybe Word8)
    -- Left "could not parse: `seven' (input does not start with a digit)"
    -- >>> parseMaybe "age" [("age", "777")] :: Either Text (Maybe Word8)
    -- Left "out of bounds: `777' (should be between 0 and 255)"
    -- >>> parseMaybe "age" [("age", "7")] :: Either Text (Maybe Word8)
    -- Right (Just 7)
    parseMaybe :: FromHttpApiData v => Text -> Form -> Either Text (Maybe v)
    parseMaybe :: forall v.
    FromHttpApiData v =>
    Text -> Form -> Either Text (Maybe v)
    parseMaybe Text
    key = Maybe Text -> Either Text (Maybe v)
    forall (t :: * -> *) a.
    (Traversable t, FromHttpApiData a) =>
    t Text -> Either Text (t a)
    parseQueryParams (Maybe Text -> Either Text (Maybe v))
    -> (Form -> Either Text (Maybe Text))
    -> Form
    -> Either Text (Maybe v)
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Text -> Form -> Either Text (Maybe Text)
    lookupMaybe Text
    key

    -- | Lookup a unique value for a given key and parse it with 'parseQueryParam'.
    -- Fail if there is zero or more than one value for the key.
    --
    -- >>> parseUnique "age" [] :: Either Text Word8
    -- Left "Could not find key \"age\""
    -- >>> parseUnique "age" [("age", "12"), ("age", "25")] :: Either Text Word8
    -- Left "Duplicate key \"age\""
    -- >>> parseUnique "age" [("age", "seven")] :: Either Text Word8
    -- Left "could not parse: `seven' (input does not start with a digit)"
    -- >>> parseUnique "age" [("age", "777")] :: Either Text Word8
    -- Left "out of bounds: `777' (should be between 0 and 255)"
    -- >>> parseUnique "age" [("age", "7")] :: Either Text Word8
    -- Right 7
    parseUnique :: FromHttpApiData v => Text -> Form -> Either Text v
    parseUnique :: forall v. FromHttpApiData v => Text -> Form -> Either Text v
    parseUnique Text
    key Form
    form = Text -> Form -> Either Text Text
    lookupUnique Text
    key Form
    form Either Text Text -> (Text -> Either Text v) -> Either Text v
    forall a b. Either Text a -> (a -> Either Text b) -> Either Text b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Text -> Either Text v
    forall a. FromHttpApiData a => Text -> Either Text a
    parseQueryParam

    -- | 'Generic'-based deriving options for 'ToForm' and 'FromForm'.
    --
    -- A common use case for non-default 'FormOptions'
    -- is to strip a prefix off of field labels:
    --
    -- @
    -- data Project = Project
    --   { projectName :: String
    --   , projectSize :: Int
    --   } deriving ('Generic', 'Show')
    --
    -- myOptions :: 'FormOptions'
    -- myOptions = 'FormOptions'
    --  { 'fieldLabelModifier' = 'map' 'toLower' . 'drop' ('length' \"project\") }
    --
    -- instance 'ToForm' Project where
    --   'toForm' = 'genericToForm' myOptions
    --
    -- instance 'FromForm' Project where
    --   'fromForm' = 'genericFromForm' myOptions
    -- @
    --
    -- >>> urlEncodeAsFormStable Project { projectName = "http-api-data", projectSize = 172 }
    -- "name=http-api-data&size=172"
    -- >>> urlDecodeAsForm "name=http-api-data&size=172" :: Either Text Project
    -- Right (Project {projectName = "http-api-data", projectSize = 172})
    data FormOptions = FormOptions
      { -- | Function applied to field labels. Handy for removing common record prefixes for example.
        FormOptions -> ShowS
    fieldLabelModifier :: String -> String
      }

    -- | Default encoding 'FormOptions'.
    --
    -- @
    -- 'FormOptions'
    -- { 'fieldLabelModifier' = id
    -- }
    -- @
    defaultFormOptions :: FormOptions
    defaultFormOptions :: FormOptions
    defaultFormOptions = FormOptions
      { fieldLabelModifier :: ShowS
    fieldLabelModifier = ShowS
    forall a. a -> a
    id
      }

    sortOn :: Ord b => (a -> b) -> [a] -> [a]
    sortOn :: forall b a. Ord b => (a -> b) -> [a] -> [a]
    sortOn a -> b
    f = (a -> a -> Ordering) -> [a] -> [a]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy ((a -> b) -> a -> a -> Ordering
    forall a b. Ord a => (b -> a) -> b -> b -> Ordering
    comparing a -> b
    f)