Экземпляр FromJSON для ключа HashMap нового типа

Я сделал новый тип UUID в моем заявлении представлять Text Идентификаторы.

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

...

newtype UUID =
    UUID Text
      deriving (Eq, Generic, FromJSON, ToJSON, FromField, ToField, FromText, Show, Read, Hashable)

Моему приложению нужен экземпляр FromJSON за HashMap UUID a, HashMap определяет экземпляр для HashMap Text a, есть ли способ использовать его при определении моего?

Если бы мне пришлось переопределить экземпляр, как бы я написал это? Вот эквивалент из Data.Aeson.Types.Instances:

instance (FromJSON v) => FromJSON (H.HashMap Text v) where
    parseJSON = withObject "HashMap Text a" $ H.traverseWithKey (\k v -> parseJSON v <?> Key k)

Как бы вы написали это для UUID? Где Key а также <?> определены, и как я могу легко найти это самостоятельно? Кажется, Google не помог.

1 ответ

Ваш UUID это новый тип, так что у вас есть

{-# LANGUAGE ScopedTypeVariables #-}

import Data.Coerce
-- other imports...

instance (FromJSON v) => FromJSON (HashMap UUID v) where
  parseJSON = coerce (parseJSON :: Value -> Parser (HashMap Text v)) 

Или, возможно, более простой способ

  parseJSON = fmap (fromList . map (\(x,y) -> (UUID x,y)) . toList) . parseJSON

Который просто анализирует Text HashMap, а затем преобразует его в индексированный по UUID. Тем не менее coerce версия лучше, так как она не имеет затрат времени выполнения.

Другие вопросы по тегам