FromJSON实例为newtype HashMap键

时间:2015-12-16 17:13:19

标签: haskell typeclass aeson

我在我的应用程序中创建了一个新类型UUID来表示Text个ID。

{-# 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<?>在哪里定义,我怎样才能自己轻松查看?霍格尔似乎没有帮助。

1 个答案:

答案 0 :(得分:2)

您的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版本更好,因为它没有运行时成本。