【问题标题】:How to auto derive FromJSON using Template Haskell, Aeson, and type families如何使用 Template Haskell、Aeson 和类型族自动派生 FromJSON
【发布时间】:2016-03-15 04:32:57
【问题描述】:

我想使用模板 haskell 来自动生成 ToJSON (Bar Baz) 或 FromJSON (Bar Baz) 实例。 derivedJSON 是Options -> Name -> Q [Dec] 类型,当类型带参数时,我如何构造Name 类型?

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TemplateHaskell #-}

import Data.Aeson
import Data.Aeson.TH

data Baz = Baz String

class Foo a where
  data Bar a :: *


instance Foo Baz where
  data Bar Baz = ExampleRecord { exampleField1 :: String
                               , exampleField2 :: String
                               }
data Biz = Biz String

instance Foo Biz where
  data Bar Biz = ExampleBizRecord1 { biz1 :: String } 
               | ExampleBizRecord2 { biz2 :: String }

type BarBaz = Bar Baz

-- doesn't work
deriveJSON defaultOptions (''Bar ''Baz)
deriveJSON defaultOptions mkName "Bar Baz"

-- Creates the Name but not supported by Data.Aeson.TH
derive JSON defaultOptions ''BarBaz

Foo将类型作为参数时如何使用deriveJSON?

【问题讨论】:

    标签: haskell template-haskell aeson type-families


    【解决方案1】:

    如果你尝试“显而易见”的事情,它不会起作用,但 TH 错误给出了一个有用的提示:

    Exception when trying to run compile-time code:
      Data.Aeson.TH.withType: Cannot use a data family name. Use a data family instance constructor instead.
    Code: deriveJSON defaultOptions ''Bar
    

    按照建议行事似乎有效:

    deriveJSON defaultOptions 'ExampleRecord 
    

    给你一个instance {From/To}JSON (Bar Baz)


    同样的事情也适用于更新示例。只需使用任何一个构造函数名称:

    data Biz = Biz String
    
    instance Foo Biz where
      data Bar Biz = ExampleBizRecord1 { biz1 :: String } 
                   | ExampleBizRecord2 { biz2 :: String }
    
    deriveJSON defaultOptions 'ExampleBizRecord1 
    -- XOR 
    deriveJSON defaultOptions 'ExampleBizRecord2 
    

    【讨论】:

    • 好吧,如果数据类型看起来像这样data Bar Baz = ExampleRecord1 String | ExampleRecord2,那不可能吧?因为那样你会得到重复的实例。
    • 这不是一个有效的数据类型声明。但是,您可以拥有data Bar a = ..。如何使用 TH 函数确实取决于数据类型是否为数据族。
    • 对不起,我不太明白。我编辑了我的问题以表明我还想为Bar Biz 自动生成实例。或者这根本不可能?
    • 查看我的编辑。新示例在与当前主题相关的任何方面都与旧示例没有区别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 2013-08-31
    • 1970-01-01
    相关资源
    最近更新 更多