首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为类型(* -> *) -> *编写aeson ->实例?

如何为类型(* -> *) -> *编写aeson ->实例?
EN

Stack Overflow用户
提问于 2018-06-23 21:20:14
回答 1查看 449关注 0票数 3

动机

我有一个类型,MyType,它是由函子f参数化的。

我希望使用MyType Identity来表示数据的“我的视图”,使用MyType Maybe来表示数据的更新类型。

问题

是否有可能为ToJSON编写一个伊索MyType实例?我试着使用ToJSON类,但是我得到了一个错误(参见post的底部)。

代码语言:javascript
复制
{-# LANGUAGE DeriveGeneric #-}
module Main where

import GHC.Generics
import Data.Aeson

data MyType f = MyType
  { age  :: f Int
  , name :: f String
  } deriving(Generic)

instance ToJSON1 f => ToJSON (MyType f)

main :: IO ()
main = print . encode $ MyType (Just 1) (Just "hi")

如何获得MyType fMyType f实例和任意f的实例

编译错误

代码语言:javascript
复制
Main.hs:12:10: error:
    • Could not deduce (ToJSON (f String))
        arising from a use of ‘aeson-1.2.4.0:Data.Aeson.Types.ToJSON.$dmtoJSON’
      from the context: ToJSON1 f
        bound by the instance declaration
        at Main.hs:12:10-39
    • In the expression:
        aeson-1.2.4.0:Data.Aeson.Types.ToJSON.$dmtoJSON @MyType f
      In an equation for ‘toJSON’:
          toJSON = aeson-1.2.4.0:Data.Aeson.Types.ToJSON.$dmtoJSON @MyType f
      In the instance declaration for ‘ToJSON (MyType f)’
   |
12 | instance ToJSON1 f => ToJSON (MyType f)
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-24 18:24:30

在使用Lifting类的评论中使用了我的想法,经过一些修改之后,我得出了以下结论

代码语言:javascript
复制
{-# LANGUAGE DeriveGeneric
           , FlexibleContexts   
           , MultiParamTypeClasses
           , ScopedTypeVariables
           , TypeApplications
           , UndecidableInstances 
           #-}
module Main where

import GHC.Generics
import Data.Aeson
import Data.Constraint
import Data.Constraint.Lifting

data MyType f = MyType
  { age  :: f Int
  , name :: f String
  } deriving(Generic)

instance (Lifting ToJSON f) => ToJSON (MyType f) where
    toJSON mt
        | Sub Dict <- lifting @ToJSON @f @Int
        , Sub Dict <- lifting @ToJSON @f @String
            = genericToJSON defaultOptions mt

instance Lifting ToJSON Maybe where
    lifting = Sub Dict

main :: IO ()
main = print . encode $ MyType (Just 1) (Just "hi")

备注:

  • Dict在约束(如ToJSON Int)和值之间来回转换。Sub只是约束包含的构造函数。
  • lifting @ToJSON @f @Int类型应用程序语法
  • 我通过查找默认实现 for toJSON来使用toJSON。我们只需要首先用lifting手动地将一些实例放到范围内。

我希望这能帮到你。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51005138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档