@@ -321,20 +321,33 @@ class FromJSON a where
321321-- Classes and types for map keys
322322-------------------------------------------------------------------------------
323323
324+-- | Read the docs for 'ToJSONKey' first. This class is a conversion
325+-- in the opposite direction. If you have a newtype wrapper around 'Text',
326+-- the recommended way to define instances is with generalized newtype deriving:
327+--
328+-- > newtype SomeId = SomeId { getSomeId :: Text }
329+-- > deriving (Eq,Ord,Hashable,FromJSONKey)
330+--
324331class FromJSONKey a where
332+ -- | Strategy for parsing the key of a map-like container.
325333 fromJSONKey :: FromJSONKeyFunction a
326334 default fromJSONKey :: FromJSON a => FromJSONKeyFunction a
327335 fromJSONKey = FromJSONKeyValue parseJSON
336+ -- | This is similar in spirit to the 'readList' method of 'Read'.
337+ -- It makes it possible to give 'String' keys special treatment
338+ -- without using @OverlappingInstances@. End users should always
339+ -- be able to use the default implementation of this method.
328340 fromJSONKeyList :: FromJSONKeyFunction [a]
329341 default fromJSONKeyList :: FromJSON a => FromJSONKeyFunction [a]
330342 fromJSONKeyList = FromJSONKeyValue parseJSON
331343
332−-- | With GHC 7.8 + we carry around 'Coercible Text a' dictionary,
333−-- to have even some amount of safety net.
334−-- Unfortunately we cannot enforce that 'Hashable' instance agree on the type level
344+-- | With GHC 7.8+ we carry around @'Coercible' 'Text' a@ dictionary,
345+-- to give us an assurance that the program will not segfault.
346+-- Unfortunately we cannot enforce that the 'Eq' instances or the
347+-- 'Hashable' instances for 'Text' and @a@ agree.
335348--
336−-- ATM this type is intentionally not exported. FromJSONKeyFunction can be inspected,
337−-- but cannot be constructed.
349+-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'
350+-- can be inspected, but cannot be constructed.
338351data CoerceText a where
339352#if HAS_COERCIBLE
340353 CoerceText :: Coercible Text a => CoerceText a
@@ -342,12 +355,19 @@ data CoerceText a where
342355 CoerceText :: CoerceText a
343356#endif
344357
358+-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the
359+-- 'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'
360+-- instance. The other three data constructors for this type all correspond to
361+-- 'ToJSONKeyText'. Strictly speaking, 'FromJSONKeyTextParser' is more powerful than
362+-- 'FromJSONKeyText', which is in turn more powerful than 'FromJSONKeyCoerce'.
363+-- For performance reasons, these exist as three options instead of one.
345364data FromJSONKeyFunction a
346− = FromJSONKeyCoerce (CoerceText a)
347− | FromJSONKeyText (Text -> a)
348− | FromJSONKeyTextParser (Text -> Parser a)
349− | FromJSONKeyValue (Value -> Parser a)
365+ = FromJSONKeyCoerce (CoerceText a) -- ^ uses 'coerce' ('unsafeCoerce' in older GHCs)
366+ | FromJSONKeyText (Text -> a) -- ^ conversion from 'Text' that always succeeds
367+ | FromJSONKeyTextParser (Text -> Parser a) -- ^ conversion from 'Text' that may fail
368+ | FromJSONKeyValue (Value -> Parser a) -- ^ conversion for non-textual keys
350369
370+-- | Only law abiding up to interpretation
351371instance Functor FromJSONKeyFunction where
352372 fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce')
353373 fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
@@ -356,7 +376,9 @@ instance Functor FromJSONKeyFunction where
356376
357377-- | Construct 'FromJSONKeyFunction' for types coercible from 'Text'. This
358378-- conversion is still unsafe, as 'Hashable' and 'Eq' instances of @a@ should be
359−-- compatible with 'Text' i.e. hash values be equal for wrapped values as well.
379+-- compatible with 'Text' i.e. hash values should be equal for wrapped values as well.
380+-- This property will always be maintained if the 'Hashable' and 'Eq' instances
381+-- are derived with generalized newtype deriving.
360382fromJSONKeyCoerce ::
361383#if HAS_COERCIBLE
362384 Coercible Text a =>