Haskell, Aeson - how to debug instances?
Question
I have a complex nested json, which i'm trying to parse with Aeson and Attoparsec, into my custom types. Based on info from questions: Haskell, Aeson & JSON parsing into custom type, Aeson: How to convert Value into custom type? and some info from Internet.
When I'm using following code I'm getting "Nothing" Value from overlapped FromJSON instance, but code goes through each instance for sure, I've tested this by disabling some other insances. So the main question : how to test code in instances and see how data changes over execution in GHCi?
P.S: Tried to set breakpoints and "trace", but they are worked only in main & parseCfg functions.
{-# LANGUAGE OverloadedStrings, FlexibleInstances #-}
-- high level data
data Cfg = Cfg { nm :: CProperty,
author :: CProperty,
langs :: CValue,
grops :: CListArr,
projs :: CPropArr
} deriving (Show)
...
instance FromJSON CProperty where
parseJSON _ = mzero
parseJSON (Object o) = CProperty <$> toCProperty o
where
toCProperty :: (HM.HashMap T.Text Value) -> J.Parser (T.Text, T.Text)
toCProperty _ = error "unexpected property"
toCProperty o' = do
l <- return $ HM.toList o'
k <- return $ fst $ head l
v <- return $ snd $ head l
v' <- parseJSON v
return $ (k, v')
... lot's of different instances
-- |this instance is specific for different files
-- based on common functions to work with most of nested json code
instance FromJSON Cfg where
parseJSON _ = mzero
parseJSON (Object o) = do
nm <- (parseJSON :: Value -> J.Parser CProperty) =<< (o .: T.pack "Name")
autor <- (parseJSON :: Value -> J.Parser CValue) =<< (o .: T.pack "Author")
langs <- (parseJSON :: Value -> J.Parser CProperty) =<< (o .: T.pack "Languages")
groups <- (parseJSON :: Value -> J.Parser CListArr) =<< (o .: T.pack "Groups")
projs <- (parseJSON :: Value -> J.Parser CPropArr) =<< (o .: T.pack "Projects")
return $ Cfg nm author langs groups projs
------------------------------------------------------------------------------------
main :: IO ()
main = do:
s <- L.readFile "/home/config.json"
-- print $ show s
let cfg = parseCfg s
print $ show $ cfg
parseCfg :: L.ByteString -> Maybe Cfg
parseCfg s = decode s
Solution
The obvious problem is that in
instance FromJSON CProperty where
parseJSON _ = mzero
parseJSON (Object o) = ...
the first clause matches all input, so your instance returns mzero
whatever the argument is. You should change the order of the clauses.
When compiling with warnings, GHC would tell you of the overlapping patterns.