2

I would like to use template haskell to auto generate the ToJSON (Bar Baz), or FromJSON (Bar Baz) instances. the deriveJSON is of type Options -> Name -> Q [Dec] how to I construct the Name type when the type takes parameters?

{-# 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

How to use the deriveJSON when Foo takes a type as a parameter?

whitehead1415
  • 435
  • 4
  • 14

1 Answers1

4

If you try the "obvious" thing it won't work, but the TH error gives a helpful hint:

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

Doing what is suggests seems to work:

deriveJSON defaultOptions 'ExampleRecord 

gets you an instance {From/To}JSON (Bar Baz).


The same thing works for the update example. Just use any one constructor name:

data Biz = Biz String

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

deriveJSON defaultOptions 'ExampleBizRecord1 
-- XOR 
deriveJSON defaultOptions 'ExampleBizRecord2 
user2407038
  • 14,400
  • 3
  • 29
  • 42
  • Ok so if the data type looked like this `data Bar Baz = ExampleRecord1 String | ExampleRecord2` then that is not possible right? because then you would get duplicate instances. – whitehead1415 Mar 14 '16 at 17:38
  • Well that isn't a valid data type declaration. You could have `data Bar a = ..` however. How you use the TH function will indeed depend on whether the datatype is a data family or not. – user2407038 Mar 14 '16 at 17:47
  • Sorry I don't quite understand. I edited my question to show that I would also like to auto generate instances for `Bar Biz`. Or is that not even possible? – whitehead1415 Mar 14 '16 at 20:24
  • See my edit. The new example doesn't differ from the old one in any way relevant to the topic at hand. – user2407038 Mar 14 '16 at 20:33