Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell ADTs with aeson

Tags:

haskell

aeson

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
like image 430
stormont Avatar asked Jan 09 '23 01:01

stormont


1 Answers

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
like image 71
zerkms Avatar answered Jan 17 '23 19:01

zerkms