+ getHeaders ∷ a → Headers
+ setHeaders ∷ a → Headers → a
+
+ modifyHeaders ∷ (Headers → Headers) → a → a
+ {-# INLINE modifyHeaders #-}
+ modifyHeaders = (setHeaders ⊛) ∘ (∘ getHeaders)
+
+ getHeader ∷ CIAscii → a → Maybe Ascii
+ {-# INLINE getHeader #-}
+ getHeader = (∘ getHeaders) ∘ lookup
+
+ hasHeader ∷ CIAscii → a → Bool
+ {-# INLINE hasHeader #-}
+ hasHeader = (∘ getHeaders) ∘ member
+
+ getCIHeader ∷ CIAscii → a → Maybe CIAscii
+ {-# INLINE getCIHeader #-}
+ getCIHeader = ((A.toCIAscii <$>) ∘) ∘ getHeader
+
+ deleteHeader ∷ CIAscii → a → a
+ {-# INLINE deleteHeader #-}
+ deleteHeader = modifyHeaders ∘ delete
+
+ setHeader ∷ CIAscii → Ascii → a → a
+ {-# INLINE setHeader #-}
+ setHeader = (modifyHeaders ∘) ∘ insertWith const
+
+instance HasHeaders Headers where
+ getHeaders = id
+ setHeaders _ = id
+
+-- |@'insert' (key, val)@ merges @val@ with an existing one if any.
+instance Unfoldable Headers (CIAscii, Ascii) where
+ {-# INLINE insert #-}
+ insert (key, val) (Headers m)
+ = Headers $ insertWith merge key val m
+ {-# INLINE empty #-}
+ empty = Headers empty
+ {-# INLINE singleton #-}
+ singleton = Headers ∘ singleton
+
+-- FIXME: auto-derive
+instance Foldable Headers (CIAscii, Ascii) where
+ {-# INLINE fold #-}
+ fold (Headers m) = fold m
+ {-# INLINE foldMap #-}
+ foldMap f (Headers m) = foldMap f m
+ {-# INLINE foldr #-}
+ foldr f b (Headers m) = foldr f b m
+ {-# INLINE foldl #-}
+ foldl f b (Headers m) = foldl f b m
+ {-# INLINE foldr1 #-}
+ foldr1 f (Headers m) = foldr1 f m
+ {-# INLINE foldl1 #-}
+ foldl1 f (Headers m) = foldl1 f m
+ {-# INLINE null #-}
+ null (Headers m) = null m
+ {-# INLINE size #-}
+ size (Headers m) = size m
+ {-# INLINE isSingleton #-}
+ isSingleton (Headers m) = isSingleton m
+
+-- FIXME: auto-derive
+instance Collection Headers (CIAscii, Ascii) where
+ {-# INLINE filter #-}
+ filter f (Headers m) = Headers $ filter f m
+
+-- FIXME: auto-derive
+instance Indexed Headers CIAscii Ascii where
+ {-# INLINE index #-}
+ index k (Headers m) = index k m
+ {-# INLINE adjust #-}
+ adjust f k (Headers m) = Headers $ adjust f k m
+ {-# INLINE inDomain #-}
+ inDomain k (Headers m) = inDomain k m
+ {-# INLINE (//) #-}
+ Headers m // l = Headers $ m // l
+ {-# INLINE accum #-}
+ accum f (Headers m) l = Headers $ accum f m l
+
+instance Monoid Headers where
+ {-# INLINE mempty #-}
+ mempty = empty
+ {-# INLINE mappend #-}
+ mappend = insertMany
+
+-- FIXME: auto-derive
+instance Map Headers CIAscii Ascii where
+ {-# INLINE delete #-}
+ delete k (Headers m) = Headers $ delete k m
+ {-# INLINE member #-}
+ member k (Headers m) = member k m
+ {-# INLINE union #-}
+ union (Headers α) (Headers β)
+ = Headers $ union α β
+ {-# INLINE intersection #-}
+ intersection (Headers α) (Headers β)
+ = Headers $ intersection α β
+ {-# INLINE difference #-}
+ difference (Headers α) (Headers β)
+ = Headers $ difference α β
+ {-# INLINE isSubset #-}
+ isSubset (Headers α) (Headers β)
+ = isSubset α β
+ {-# INLINE isProperSubset #-}
+ isProperSubset (Headers α) (Headers β)
+ = isProperSubset α β
+ {-# INLINE lookup #-}
+ lookup k (Headers m) = lookup k m
+ {-# INLINE alter #-}
+ alter f k (Headers m)
+ = Headers $ alter f k m
+ {-# INLINE insertWith #-}
+ insertWith f k v (Headers m)
+ = Headers $ insertWith f k v m
+ {-# INLINE fromFoldableWith #-}
+ fromFoldableWith = (Headers ∘) ∘ fromFoldableWith
+ {-# INLINE foldGroups #-}
+ foldGroups = ((Headers ∘) ∘) ∘ foldGroups
+ {-# INLINE mapWithKey #-}
+ mapWithKey f (Headers m)
+ = Headers $ mapWithKey f m
+ {-# INLINE unionWith #-}
+ unionWith f (Headers α) (Headers β)
+ = Headers $ unionWith f α β
+ {-# INLINE intersectionWith #-}
+ intersectionWith f (Headers α) (Headers β)
+ = Headers $ intersectionWith f α β
+ {-# INLINE differenceWith #-}
+ differenceWith f (Headers α) (Headers β)
+ = Headers $ differenceWith f α β
+ {-# INLINE isSubmapBy #-}
+ isSubmapBy f (Headers α) (Headers β)
+ = isSubmapBy f α β
+ {-# INLINE isProperSubmapBy #-}
+ isProperSubmapBy f (Headers α) (Headers β)
+ = isProperSubmapBy f α β
+
+-- FIXME: auto-derive
+instance SortingCollection Headers (CIAscii, Ascii) where
+ {-# INLINE minView #-}
+ minView (Headers m) = second Headers <$> minView m
+
+merge ∷ Ascii → Ascii → Ascii
+{-# INLINE merge #-}
+merge a b
+ | nullA a ∧ nullA b = (∅)
+ | nullA a = b
+ | nullA b = a
+ | otherwise = a ⊕ ", " ⊕ b
+ where
+ nullA ∷ Ascii → Bool
+ {-# INLINE nullA #-}
+ nullA = null ∘ A.toByteString