4

I've been fighting with a simple ADT, trying to get it to round-trip back and forth to JSON, but I've had no luck, no matter how I try to massage or modify the type. What am I missing?

When it compiles, I always get the same runtime error:

> let t = Fahrenheit
> fromJSON $ toJSON t
Error "when expecting a (), encountered Object instead"

Trying this just gives me "Nothing", presumably because of the same error: decode $ encode t

I've tried to follow these sources, but I can't seem to get around this runtime error, no matter what I try: Haskell :: Aeson :: parse ADT based on field value https://www.fpcomplete.com/user/Geraldus/algebraic-data-types-adts-with-aeson

Here's one form of the code I'm using. At first, I tried to use this as a type embedded in another type, but when that didn't work I added the "value" key to try to make parsing of this easier (no luck).

data TemperatureType = Celsius
                     | Fahrenheit
                     deriving (Show,Read,Typeable,Data,Eq)

-- This doesn't work either
-- $(deriveJSON defaultOptions ''TemperatureType)

instance ToJSON TemperatureType where
   toJSON Fahrenheit = object [ "value" .= String "Fahrenheit" ]
   toJSON Celsius    = object [ "value" .= String "Celsius" ]

instance FromJSON TemperatureType where
    parseJSON (Object x) = toTemperatureType <$> x .: "value"

toTemperatureType :: Text -> TemperatureType
toTemperatureType "Fahrenheit" = Fahrenheit
toTemperatureType "Celsius"    = Celsius
Community
  • 1
  • 1
stormont
  • 539
  • 5
  • 16
  • 1
    (super newbie here) what if you help haskell and tell what type the expressoin is? `fromJSON $ toJSON t :: TemperatureType` – zerkms Jan 26 '15 at 00:55
  • 1
    There's no witness to what type you are expecting from "fromJSON", you have to assign the type as @zerkms recommended. Consider the case of: "Read a => String -> Maybe a" and it becomes more obvious why this would be the case. – bitemyapp Jan 26 '15 at 01:02
  • No, that's a great idea. Turns out, `(fromJSON $ toJSON t) :: Result TemperatureType` works, as does `(decode $ encode t) :: Maybe TemperatureType`. Still seems to fail as an embedded value in another type, though. There must be more "manual" types I can specify. Strange that this compiles without ambiguity. – stormont Jan 26 '15 at 01:02
  • Ah, right `:: Result TemperatureType` "Still seems to fail as an embedded value in another type, though" --- keen to share? – zerkms Jan 26 '15 at 01:04
  • Ah, got it working in my wrapper type. The extra issue there seemed to be how I was encoding the other value. The same error message was appearing, making this ambiguous. Want to post your response as a solution, so I can select it as the answer? – stormont Jan 26 '15 at 01:11

1 Answers1

9

Haskell need help from you about the type of your expression result since in the current call it's not possible to infer it:

> fromJSON $ toJSON t :: Result TemperatureType
zerkms
  • 249,484
  • 69
  • 436
  • 539