@@ -20,7 +20,12 @@ import Control.Arrow ((***))
2020import Control.Monad ((<=<))
2121import qualified Data.ByteString.Lazy as BSL
2222import qualified Data.ByteString.Lazy.Char8 as BSL8
23+import Data.Hashable (Hashable)
24+import Data.HashMap.Strict (HashMap)
25+import qualified Data.HashMap.Strict as HashMap
2326import Data.Int
27+import Data.IntMap (IntMap)
28+import qualified Data.IntMap as IntMap
2429import Data.Map (Map)
2530import qualified Data.Map as Map
2631import Data.Monoid
@@ -201,7 +206,17 @@ instance (ToFormKey k, ToHttpApiData v) => ToForm [(k, v)] where
201206 toForm = fromList . map (toFormKey *** toQueryParam)
202207
203208instance (ToFormKey k, ToHttpApiData v) => ToForm (Map k [v]) where
204− toForm = Form . Map.fromListWith (<>) . map (toFormKey *** map toQueryParam) . Map.toList
209+ toForm = fromEntriesByKey . Map.toList
210+
211+instance (ToFormKey k, ToHttpApiData v) => ToForm (HashMap k [v]) where
212+ toForm = fromEntriesByKey . HashMap.toList
213+
214+instance ToHttpApiData v => ToForm (IntMap [v]) where
215+ toForm = fromEntriesByKey . IntMap.toList
216+
217+-- | Convert a list of entries groupped by key into a 'Form'.
218+fromEntriesByKey :: (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form
219+fromEntriesByKey = Form . Map.fromListWith (<>) . map (toFormKey *** map toQueryParam)
205220
206221-- | A 'Generic'-based implementation of 'toForm'.
207222-- This is used as a default implementation in 'ToForm'.
@@ -273,14 +288,20 @@ class FromForm a where
273288instance FromForm Form where fromForm = pure
274289
275290instance (FromFormKey k, FromHttpApiData v) => FromForm [(k, v)] where
276− fromForm = fmap (concatMap (\(k, vs) -> map ((,) k) vs)) . entriesByKey
291+ fromForm = fmap (concatMap (\(k, vs) -> map ((,) k) vs)) . toEntriesByKey
277292
278293instance (Ord k, FromFormKey k, FromHttpApiData v) => FromForm (Map k [v]) where
279− fromForm = fmap (Map.fromListWith (<>)) . entriesByKey
294+ fromForm = fmap (Map.fromListWith (<>)) . toEntriesByKey
295+
296+instance (Eq k, Hashable k, FromFormKey k, FromHttpApiData v) => FromForm (HashMap k [v]) where
297+ fromForm = fmap (HashMap.fromListWith (<>)) . toEntriesByKey
298+
299+instance FromHttpApiData v => FromForm (IntMap [v]) where
300+ fromForm = fmap (IntMap.fromListWith (<>)) . toEntriesByKey
280301
281302-- | Parse a 'Form' into a list of entries groupped by key.
282−entriesByKey :: (FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])]
283−entriesByKey = traverse parseGroup . Map.toList . unForm
303+toEntriesByKey :: (FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])]
304+toEntriesByKey = traverse parseGroup . Map.toList . unForm
284305 where
285306 parseGroup (k, vs) = (,) <$> parseFormKey k <*> traverse parseQueryParam vs
286307