git.iko.soy/typeable/http-api-data
on master help sign in
Add more docs explaining special roles of Maybe and lists
commitf59b5c93ddfcde09146ed7655f63cfc420ab38af authorNickolay Kudasov <nickolay.kudasov@gmail.com> dateWed 31 Aug 2016, 04:26 (10 years ago) parentde9fe0f
1 file changed+51−1
src/Web/Internal/FormUrlEncoded.hs+51−1
src/Web/Internal/FormUrlEncoded.hs+51−1
@@ -75,6 +75,10 @@ import Web.Internal.HttpApiData
7575-- >>> instance ToForm Person
7676-- >>> instance FromForm Person
7777--
78+-- >>> data Post = Post { title :: String, subtitle :: Maybe String, comments :: [String]} deriving (Generic, Show)
79+-- >>> instance ToForm Post
80+-- >>> instance FromForm Post
81+--
7882-- >>> data Project = Project { projectName :: String, projectSize :: Int } deriving (Generic, Show)
7983-- >>> let myOptions = FormOptions { fieldLabelModifier = map toLower . drop (length ("project" :: String)) }
8084-- >>> instance ToForm Project where toForm = genericToForm myOptions
@@ -225,7 +229,6 @@ instance IsList Form where
225229-- @
226230--
227231-- The default implementation of 'toForm' is 'genericToForm'.
228−-- It only works for records and it will use 'toQueryParam' for each field's value.
229232class ToForm a where
230233 -- | Convert a value into 'Form'.
231234 toForm :: a -> Form
@@ -278,6 +281,30 @@ type family NotSupported (cls :: k1) (a :: k2) (reason :: Symbol) :: Constraint
278281-- , age :: Int
279282-- } deriving ('Generic')
280283-- @
284+--
285+-- In this implementation each field's value gets encoded using `toQueryParam`.
286+-- Two field types are exceptions:
287+--
288+-- - for values of type @'Maybe' a@ an entry is added to the 'Form' only when it is @'Just' x@
289+-- and the encoded value is @'toQueryParam' x@; 'Nothing' values are omitted from the 'Form';
290+--
291+-- - for values of type @[a]@ (except @['Char']@) an entry is added for every item in the list;
292+-- if the list is empty no entries are added to the 'Form';
293+--
294+-- Here's an example:
295+--
296+-- @
297+-- data Post = Post
298+-- { title :: String
299+-- , subtitle :: Maybe String
300+-- , comments :: [String]
301+-- } deriving ('Generic', 'Show')
302+--
303+-- instance 'ToForm' Post
304+-- @
305+--
306+-- >>> urlEncodeAsForm Post { title = "Test", subtitle = Nothing, comments = ["Nice post!", "+1"] }
307+-- "comments=Nice%20post%21&comments=%2B1&title=Test"
281308genericToForm :: forall a. (Generic a, GToForm a (Rep a)) => FormOptions -> a -> Form
282309genericToForm opts = gToForm (Proxy :: Proxy a) opts . from
283310
@@ -393,6 +420,29 @@ toEntriesByKey = traverse parseGroup . HashMap.toList . unForm
393420-- , age :: Int
394421-- } deriving ('Generic')
395422-- @
423+--
424+-- In this implementation each field's value gets decoded using `parseQueryParam`.
425+-- Two field types are exceptions:
426+--
427+-- - for values of type @'Maybe' a@ an entry is parsed if present in the 'Form'
428+-- and the is decoded with 'parseQueryParam'; if no entry is present result is 'Nothing';
429+--
430+-- - for values of type @[a]@ (except @['Char']@) all entries are parsed to produce a list of parsed values;
431+--
432+-- Here's an example:
433+--
434+-- @
435+-- data Post = Post
436+-- { title :: String
437+-- , subtitle :: Maybe String
438+-- , comments :: [String]
439+-- } deriving ('Generic', 'Show')
440+--
441+-- instance 'FromForm' Post
442+-- @
443+--
444+-- >>> urlDecodeAsForm "comments=Nice%20post%21&comments=%2B1&title=Test" :: Either Text Post
445+-- Right (Post {title = "Test", subtitle = Nothing, comments = ["Nice post!","+1"]})
396446genericFromForm :: forall a. (Generic a, GFromForm a (Rep a)) => FormOptions -> Form -> Either Text a
397447genericFromForm opts f = to <$> gFromForm (Proxy :: Proxy a) opts f
398448