Aeson 2.0.3.0环境下Store实例缺失问题求助
Aeson 2.x 下为Store生成孤儿实例的编译问题修复
问题背景
原本为store库生成Aeson类型孤儿实例的代码,在aeson 1.4.7.1(搭配store 0.7.1、Stackage LTS-16.31)环境可正常运行,但升级至aeson 2.0.3.0(搭配store 0.7.16、Stackage LTS-20.13)后编译报错,提示缺少Aeson内部Object类型的Store实例。
编译错误信息
No instance for (Store aeson-2.0.3.0:Data.Aeson.Types.Internal.Object) arising from a use of ‘store-0.7.16:Data.Store.Impl.size’
原可运行代码(aeson 1.x环境)
{-# LANGUAGE DeriveDataTypeable,DeriveGeneric,TemplateHaskell,GeneralizedNewtypeDeriving, OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans #-} import Data.Store (Store) import TH.Derive import Data.Scientific import Data.Aeson (Value) -- 为Aeson对象提供序列化支持 $($(derive [d| instance Deriving (Store (Scientific)) |])) $($(derive [d| instance Deriving (Store (Value)) |])) -- 用Template Haskell推导Value的Store实例
已尝试的修改
根据建议添加了Key和KeyMap的实例推导(需启用ScopedTypeVariables扩展):
$($(derive [d| instance Deriving (Store (Key)) |])) $($(derive [d| instance Store a => Deriving (Store (KeyMap a)) |]))
完整修复方案
aeson 2.x对Object的实现做了重构:原Object是HashMap Text Value,现在改为KeyMap Value,同时新增Key类型作为Text的包装器。要修复编译错误,需为所有依赖类型生成Store实例,步骤如下:
1. 补充必要的语言扩展与导入
添加ScopedTypeVariables扩展,并导入Aeson内部的Object、Key、KeyMap类型:
{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, TemplateHaskell, GeneralizedNewtypeDeriving, OverloadedStrings, ScopedTypeVariables #-} {-# OPTIONS_GHC -fno-warn-orphans #-} import Data.Store (Store) import TH.Derive import Data.Scientific import Data.Aeson (Value) import Data.Aeson.Types.Internal (Object, Key, KeyMap)
2. 按依赖顺序推导Store实例
需先推导基础类型的实例,再推导依赖它们的复杂类型:
-- 推导Scientific的Store实例 $($(derive [d| instance Deriving (Store Scientific) |])) -- 推导Key的Store实例(Key是Text的包装类型,需先于KeyMap推导) $($(derive [d| instance Deriving (Store Key) |])) -- 推导KeyMap的通用Store实例(需ScopedTypeVariables扩展) $($(derive [d| instance Store a => Deriving (Store (KeyMap a)) |])) -- 推导Value的Store实例(Value依赖Object,而Object是KeyMap Value) $($(derive [d| instance Deriving (Store Value) |])) -- 显式推导Object的Store实例(可选,因Object等价于KeyMap Value,已被上面的KeyMap实例覆盖,显式声明更清晰) $($(derive [d| instance Deriving (Store Object) |]))
修复原理
aeson 2.x中Value类型的构造器包含Object,而Object现在基于自定义的KeyMap和Key类型。只有先为Key和KeyMap生成Store实例,Value的Store实例才能正常编译,解决缺失Object实例的报错。
内容的提问来源于stack exchange,提问作者Sal
相关产品推荐
相关产品推荐

