[英]Can I reuse ToJSON and FromJSON instances between Data.Aeson and Data.Yaml?
Data.Aeson和Data.Yaml是分別用於JSON和YAML的庫,它們具有幾乎相同的接口。 我為某些類型編寫了“基於Aeson的” FromJSON
和ToJSON
實例:
import Data.Aeson
data PropertyValue = Nested Microformat | Flat Text
deriving (Generic, Show)
instance ToJSON PropertyValue where
toEncoding = genericToEncoding defaultOptions { sumEncoding = UntaggedValue }
instance FromJSON PropertyValue where
parseJSON = genericParseJSON defaultOptions { sumEncoding = UntaggedValue }
雖然Aeson使用這些實例,但Yaml似乎忽略了它們。 (特別是,我相信Yaml會自動生成編碼器和解碼器,這要歸功於我的類型派生了Generic
。)我試圖通過將代碼更改為Yaml,使實例也能與Yaml一起使用
import Data.Aeson
import qualified Data.Yaml as Y
data PropertyValue = Nested Microformat | Flat Text
deriving (Generic, Show)
instance ToJSON PropertyValue where
toEncoding = genericToEncoding defaultOptions { sumEncoding = UntaggedValue }
instance FromJSON PropertyValue where
parseJSON = genericParseJSON defaultOptions { sumEncoding = UntaggedValue }
instance Y.ToJSON PropertyValue where
toEncoding = genericToEncoding defaultOptions { sumEncoding = UntaggedValue }
instance Y.FromJSON PropertyValue where
parseJSON = genericParseJSON defaultOptions { sumEncoding = UntaggedValue }
但GHC抱怨:
Duplicate instance declarations:
instance ToJSON PropertyValue
-- Defined at src/Microformats.hs:54:10
instance ToJSON PropertyValue
-- Defined at src/Microformats.hs:60:10
是否無法為碰巧具有相同名稱的兩個不同類定義實例? 還是Yaml的ToJSON
實際上與 Aeson的類相同 ?
更重要的是,是否有可能重用我的ToJSON
和FromJSON
實例,而不必兩次編寫相同的代碼? 失敗了,是否至少可以在不混淆編譯器的情況下編寫兩個庫的ToJSON
和FromJSON
實例?
簡短的回答 :在ToJSON
(和FromJSON
的)類型類Data.Aeson
和Data.Yaml
是相同的 。 Data.Yaml
實際上只執行的重新導入 ToJSON
的類型類Data.Aeson
。
如果我們看一下Data.Yaml
源代碼 :
(......)#if (defined (ghcjs_HOST_OS)) module Data.Yaml {-# WARNING "GHCJS is not supported yet (will break at runtime once called)." #-} #else module Data.Yaml #endif ( -- * Types Value (..) , Parser , Object , Array , ParseException(..) , prettyPrintParseException , YamlException (..) , YamlMark (..) -- * Constructors and accessors , object , array , (.=) , (.:) , (.:?) , (.!=) -- ** With helpers (since 0.8.23) , withObject , withText , withArray , withScientific , withBool -- * Parsing , parseMonad , parseEither , parseMaybe -- * Classes , ToJSON (..) , FromJSON (..) -- * Encoding/decoding , encode , encodeFile , decode , decodeFile -- ** Better error information , decodeEither , decodeEither' , decodeFileEither -- ** More control over decoding , decodeHelper ) where #if !MIN_VERSION_base(4,8,0) import Control.Applicative(()) #endif import Control.Exception import Data.Aeson ( Value (..), ToJSON (..), FromJSON (..) , object , (.=) , (.:) , (.:?) , (.!=) , Object, Array , withObject, withText, withArray, withScientific, withBool )
因此,模塊將導出ToJSON
類型類,但這僅是ToJSON
導入的Data.Aeson
,因此類型類實際上是完全相同的。
因此,為了方便程序員而將其重新導入(例如,您不必導入Data.Aeson
僅實現FromJOSN
),但實際上您仍然使用相同的類型,相同的類型類等。畢竟, ToJSON
和Y.ToJSON
引用相同的類型類。
由於兩者實際上是相同的,因此您無法為相同類型實例化相同的類型類兩次,但是我們不需要這樣做:如果我們為Data.Aeson
(或Data.Yaml
)實現它, Data.Aeson
足夠了,因為例如,用Data.Yaml
(或Data.Aeson
)編寫的類型類約束將成功。 結果是,我們不能(至少沒有一些技巧) ToJSON
不同於Data.Yaml
實現Data.Aeson
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.