@@ -228,7 +228,7 @@ class ToForm a where
228228 -- | Convert a value into 'Form'.
229229 toForm :: a -> Form
230230 default toForm :: (Generic a, GToForm a (Rep a)) => a -> Form
231− toForm = genericToForm
231+ toForm = genericToForm defaultFormOptions
232232
233233instance ToForm Form where toForm = id
234234
@@ -274,25 +274,25 @@ type family NotSupported (cls :: k1) (a :: k2) (reason :: Symbol) :: Constraint
274274-- , age :: Int
275275-- } deriving ('Generic')
276276-- @
277−genericToForm :: forall a. (Generic a, GToForm a (Rep a)) => a -> Form
278−genericToForm = gToForm (Proxy :: Proxy a) . from
277+genericToForm :: forall a. (Generic a, GToForm a (Rep a)) => FormOptions -> a -> Form
278+genericToForm opts = gToForm (Proxy :: Proxy a) opts . from
279279
280280class GToForm t (f :: * -> *) where
281− gToForm :: Proxy t -> f x -> Form
281+ gToForm :: Proxy t -> FormOptions -> f x -> Form
282282
283283instance (GToForm t f, GToForm t g) => GToForm t (f :*: g) where
284− gToForm p (a :*: b) = gToForm p a <> gToForm p b
284+ gToForm p opts (a :*: b) = gToForm p opts a <> gToForm p opts b
285285
286286instance (GToForm t f) => GToForm t (M1 D x f) where
287− gToForm p (M1 a) = gToForm p a
287+ gToForm p opts (M1 a) = gToForm p opts a
288288
289289instance (GToForm t f) => GToForm t (M1 C x f) where
290− gToForm p (M1 a) = gToForm p a
290+ gToForm p opts (M1 a) = gToForm p opts a
291291
292292instance (Selector s, ToHttpApiData c) => GToForm t (M1 S s (K1 i c)) where
293− gToForm _ (M1 (K1 c)) = fromList [(key, toQueryParam c)]
293+ gToForm _ opts (M1 (K1 c)) = fromList [(key, toQueryParam c)]
294294 where
295− key = Text.pack $ selName (Proxy3 :: Proxy3 s g p)
295+ key = Text.pack $ fieldLabelModifier opts $ selName (Proxy3 :: Proxy3 s g p)
296296
297297instance NotSupported ToForm t "is a sum type" => GToForm t (f :+: g) where gToForm = error "impossible"
298298
@@ -335,7 +335,7 @@ class FromForm a where
335335 -- | Parse 'Form' into a value.
336336 fromForm :: Form -> Either Text a
337337 default fromForm :: (Generic a, GFromForm a (Rep a)) => Form -> Either Text a
338− fromForm = genericFromForm
338+ fromForm = genericFromForm defaultFormOptions
339339
340340instance FromForm Form where fromForm = pure
341341
@@ -371,25 +371,25 @@ toEntriesByKey = traverse parseGroup . HashMap.toList . unForm
371371-- , age :: Int
372372-- } deriving ('Generic')
373373-- @
374−genericFromForm :: forall a. (Generic a, GFromForm a (Rep a)) => Form -> Either Text a
375−genericFromForm f = to <$> gFromForm (Proxy :: Proxy a) f
374+genericFromForm :: forall a. (Generic a, GFromForm a (Rep a)) => FormOptions -> Form -> Either Text a
375+genericFromForm opts f = to <$> gFromForm (Proxy :: Proxy a) opts f
376376
377377class GFromForm t (f :: * -> *) where
378− gFromForm :: Proxy t -> Form -> Either Text (f x)
378+ gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (f x)
379379
380380instance (GFromForm t f, GFromForm t g) => GFromForm t (f :*: g) where
381− gFromForm p f = (:*:) <$> gFromForm p f <*> gFromForm p f
381+ gFromForm p opts f = (:*:) <$> gFromForm p opts f <*> gFromForm p opts f
382382
383383instance (Selector s, FromHttpApiData f) => GFromForm t (M1 S s (K1 i f)) where
384− gFromForm _ form = M1 . K1 <$> parseUnique key form
384+ gFromForm _ opts form = M1 . K1 <$> parseUnique key form
385385 where
386− key = Text.pack $ selName (Proxy3 :: Proxy3 s g p)
386+ key = Text.pack $ fieldLabelModifier opts $ selName (Proxy3 :: Proxy3 s g p)
387387
388388instance GFromForm t f => GFromForm t (M1 D x f) where
389− gFromForm p f = M1 <$> gFromForm p f
389+ gFromForm p opts f = M1 <$> gFromForm p opts f
390390
391391instance GFromForm t f => GFromForm t (M1 C x f) where
392− gFromForm p f = M1 <$> gFromForm p f
392+ gFromForm p opts f = M1 <$> gFromForm p opts f
393393
394394instance NotSupported FromForm t "is a sum type" => GFromForm t (f :+: g) where gFromForm = error "impossible"
395395
@@ -551,3 +551,20 @@ parseAll key = parseQueryParams . lookupAll key
551551parseUnique :: FromHttpApiData v => Text -> Form -> Either Text v
552552parseUnique key form = lookupUnique key form >>= parseQueryParam
553553
554+-- | 'Generic'-based deriving options for 'ToForm' and 'FromForm'.
555+data FormOptions = FormOptions
556+ { -- | Function applied to field labels. Handy for removing common record prefixes for example.
557+ fieldLabelModifier :: String -> String
558+ }
559+
560+-- | Default encoding 'FormOptions'.
561+--
562+-- @
563+-- 'FormOptions'
564+-- { 'fieldLabelModifier' = id
565+-- }
566+-- @
567+defaultFormOptions :: FormOptions
568+defaultFormOptions = FormOptions
569+ { fieldLabelModifier = id
570+ }