1
votes

I'm trying to write a somehow generic instance for FromJSON typeclass. The idea is to use the datatype name during parsing of the JSON. I would think that's something which GHC should be able to do, but so far my attempts fail. The simplest version, using Typeable typeclass is below.

data GetResponse a = GetResponse { getCode :: Int, getItem :: a } deriving (Show)

instance (Typeable a, FromJSON a) => FromJSON (GetResponse a) where
    parseJSON =
      withObject "GetResponse" $ \o -> do
          getCode <- o .: "code"
          getItem <- o .: toLower (pack typeName)

          return GetResponse {..}
        where
          typeName = showsTypeRep (typeRep Proxy :: Proxy a) ""

It fails to compile with the following error:

[1 of 1] Compiling Main             ( generics.hs, interpreted )

generics.hs:74:48: error:
    • Could not deduce (Typeable a0) arising from a use of ‘typeRep’
      from the context: (Typeable a, FromJSON a)
        bound by the instance declaration at generics.hs:66:10-61
      The type variable ‘a0’ is ambiguous
    • In the first argument of ‘showsTypeRep’, namely
        ‘(typeRep (Proxy :: Proxy a))’
      In the second argument of ‘($)’, namely
        ‘showsTypeRep (typeRep (Proxy :: Proxy a)) ""’
      In the second argument of ‘($)’, namely
        ‘pack $ showsTypeRep (typeRep (Proxy :: Proxy a)) ""’

I tried doing the same thing with Generics but got the same error back.

Full code: http://codepad.org/Gh3ifHkP

1

1 Answers

3
votes

Enabling the ScopedTypeVariables extension I was able to compile this example. With this extension the a in Proxy a corresponds to the same a in the instance declaration.