@@ -19,15 +19,20 @@ import Control.Applicative
1919import Control.Monad ((<=<))
2020import qualified Data.ByteString.Lazy as BSL
2121import qualified Data.ByteString.Lazy.Char8 as BSL8
22+import Data.Int
2223import Data.Map (Map)
2324import qualified Data.Map as Map
2425import Data.Monoid
2526
2627import Data.Text (Text)
2728import qualified Data.Text as Text
29+import qualified Data.Text.Lazy as Lazy
2830import Data.Text.Encoding as Text
2931import Data.Text.Encoding.Error (lenientDecode)
3032
33+import Data.Time
34+import Data.Word
35+
3136import GHC.Exts (IsList (..))
3237import GHC.Generics
3338import Network.URI (escapeURIString, isUnreserved,
@@ -48,6 +53,90 @@ import Web.Internal.HttpApiData
4853-- >>> instance ToForm Person
4954-- >>> instance FromForm Person
5055
56+-- | Typeclass for types that can be used as keys in a 'Form'-like container (like 'Map').
57+class ToFormKey k where
58+ -- | Render a key for a 'Form'.
59+ toFormKey :: k -> Text
60+
61+instance ToFormKey () where toFormKey = toQueryParam
62+instance ToFormKey Char where toFormKey = toQueryParam
63+
64+instance ToFormKey Bool where toFormKey = toQueryParam
65+instance ToFormKey Ordering where toFormKey = toQueryParam
66+
67+instance ToFormKey Double where toFormKey = toQueryParam
68+instance ToFormKey Float where toFormKey = toQueryParam
69+instance ToFormKey Int where toFormKey = toQueryParam
70+instance ToFormKey Int8 where toFormKey = toQueryParam
71+instance ToFormKey Int16 where toFormKey = toQueryParam
72+instance ToFormKey Int32 where toFormKey = toQueryParam
73+instance ToFormKey Int64 where toFormKey = toQueryParam
74+instance ToFormKey Integer where toFormKey = toQueryParam
75+instance ToFormKey Word where toFormKey = toQueryParam
76+instance ToFormKey Word8 where toFormKey = toQueryParam
77+instance ToFormKey Word16 where toFormKey = toQueryParam
78+instance ToFormKey Word32 where toFormKey = toQueryParam
79+instance ToFormKey Word64 where toFormKey = toQueryParam
80+
81+instance ToFormKey Day where toFormKey = toQueryParam
82+instance ToFormKey LocalTime where toFormKey = toQueryParam
83+instance ToFormKey ZonedTime where toFormKey = toQueryParam
84+instance ToFormKey UTCTime where toFormKey = toQueryParam
85+instance ToFormKey NominalDiffTime where toFormKey = toQueryParam
86+
87+instance ToFormKey String where toFormKey = toQueryParam
88+instance ToFormKey Text where toFormKey = toQueryParam
89+instance ToFormKey Lazy.Text where toFormKey = toQueryParam
90+
91+instance ToFormKey All where toFormKey = toQueryParam
92+instance ToFormKey Any where toFormKey = toQueryParam
93+
94+instance ToFormKey a => ToFormKey (Dual a) where toFormKey = toFormKey . getDual
95+instance ToFormKey a => ToFormKey (Sum a) where toFormKey = toFormKey . getSum
96+instance ToFormKey a => ToFormKey (Product a) where toFormKey = toFormKey . getProduct
97+
98+-- | Typeclass for types that can be parsed from keys of a 'Form'. This is the reverse of 'ToFormKey'.
99+class FromFormKey k where
100+ -- | Parse a key of a 'Form'.
101+ parseFormKey :: Text -> Either Text k
102+
103+instance FromFormKey () where parseFormKey = parseQueryParam
104+instance FromFormKey Char where parseFormKey = parseQueryParam
105+
106+instance FromFormKey Bool where parseFormKey = parseQueryParam
107+instance FromFormKey Ordering where parseFormKey = parseQueryParam
108+
109+instance FromFormKey Double where parseFormKey = parseQueryParam
110+instance FromFormKey Float where parseFormKey = parseQueryParam
111+instance FromFormKey Int where parseFormKey = parseQueryParam
112+instance FromFormKey Int8 where parseFormKey = parseQueryParam
113+instance FromFormKey Int16 where parseFormKey = parseQueryParam
114+instance FromFormKey Int32 where parseFormKey = parseQueryParam
115+instance FromFormKey Int64 where parseFormKey = parseQueryParam
116+instance FromFormKey Integer where parseFormKey = parseQueryParam
117+instance FromFormKey Word where parseFormKey = parseQueryParam
118+instance FromFormKey Word8 where parseFormKey = parseQueryParam
119+instance FromFormKey Word16 where parseFormKey = parseQueryParam
120+instance FromFormKey Word32 where parseFormKey = parseQueryParam
121+instance FromFormKey Word64 where parseFormKey = parseQueryParam
122+
123+instance FromFormKey Day where parseFormKey = parseQueryParam
124+instance FromFormKey LocalTime where parseFormKey = parseQueryParam
125+instance FromFormKey ZonedTime where parseFormKey = parseQueryParam
126+instance FromFormKey UTCTime where parseFormKey = parseQueryParam
127+instance FromFormKey NominalDiffTime where parseFormKey = parseQueryParam
128+
129+instance FromFormKey String where parseFormKey = parseQueryParam
130+instance FromFormKey Text where parseFormKey = parseQueryParam
131+instance FromFormKey Lazy.Text where parseFormKey = parseQueryParam
132+
133+instance FromFormKey All where parseFormKey = parseQueryParam
134+instance FromFormKey Any where parseFormKey = parseQueryParam
135+
136+instance FromFormKey a => FromFormKey (Dual a) where parseFormKey = fmap Dual . parseFormKey
137+instance FromFormKey a => FromFormKey (Sum a) where parseFormKey = fmap Sum . parseFormKey
138+instance FromFormKey a => FromFormKey (Product a) where parseFormKey = fmap Product . parseFormKey
139+
51140-- | The contents of a form, not yet URL-encoded.
52141--
53142-- 'Form' can be URL-encoded with 'encodeForm' and URL-decoded with 'decodeForm'.