I think the answer to your question revolves around the Alternative instance for Parser. Does the following code help?Var <$> ((Left <$> parseJSON) <|> (Right <$> parseJSON))What this is saying is "try to parse a MyList, and then wrap it with a Left. If that fails, try to parse an Item and wrap it with a Right. Whatever the result is from there, wrap it in a Var."On Sat, May 2, 2015 at 3:56 PM Johannes Strecha <j.strecha@gmail.com> wrote:_______________________________________________Johannes.Regards,The question is how I can decode test.yaml to get Var. Trying to code readVar like readItem (having FromJSON Var like FromJSON Item) failed. For convenience I attached the relevant source files.> c: "test">v:or, alternativelyThe file test.yaml looks likeDear Cafe,I need help parsing YAML files with varying structure. The minimal example is: a yaml file that has one key, which can hold either one key-value pair or two key value pairs. I have data types for the one key, and the two possible sub-keys:
>data Var = Var {
> v' :: Either MyList Item
> } deriving Show
>
>data MyList = MyList {
> a' :: Int,
> b' :: Int
> } deriving Show
>
>data Item = Item {
> content' :: String
> } deriving ShowTo read MyList and Item from the file I wrote FromJSON instances
>instance FromJSON MyList where
> parseJSON (Object m) = MyList <$> m .: (pack "a") <*> m .: (pack "b")
> parseJSON x = fail ("not an object: " ++ show x)
>
>instance FromJSON Item where
> parseJSON (Object m) = Item <$> m .: (pack "c")
> parseJSON x = fail ("not an object: " ++ show x)
I also have read functions for MyList and Item:
>readItem :: IO Item
>readItem = either (error.show) id <$> decodeFileEither "test.yaml"
>
>readMyList :: IO MyList
>readMyList = either (error.show) id <$> decodeFileEither "test.yaml"
>v:
> a: 4
> b: 5
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe