Open pnotequalnp opened 2 years ago
If I understand it correctly, you need to use the BiMap
related functionality rather than the preexisting TomlCodec
related functionality here, because a TomlCodec
requires looking at a specific key (or multiple specific keys). c.f. https://hackage.haskell.org/package/tomland-1.3.3.1/docs/Toml-Codec-Combinator-Common.html#v:match. You can build your own alternative to match
that does not look at a key however. I think that is the way to go here.
In the TOML datastructure itself, the root datastructures are introduced by the tree fields 'tomlPairs', 'tomlTables' and 'tomlTableArrays'. You are able to read/write these in a custom function that takes a bimap as input an creates a TomlCodec as output.
I'm having trouble coming up with the solution described here, could anyone provide an example?
I've only been able to parse a file like this by calling parse
, then manually iterating over the tomlTables
and calling runTomlCodec
on each individual value. Which leaves something to be desired in terms of validation etc.
I had trouble with this, too. I followed @thomasjm's advice, and ended up with these helpers to get me unblocked. Pasting here as a starting point in case anyone else runs into a similar situation.
keyText :: Toml.Key -> T.Text
keyText = F.fold . cleanup . map Toml.unPiece . F.toList . Toml.unKey
where
-- Top-level table names are parsed as @"name" :|
-- ["name"]@. Remove that duplication here.
cleanup [x, y] | x == y = [x]
cleanup x = x
-- | Parse a TOML file that is a top-level table whose values are all
-- the same type. The @tomland@ codec API is centered around starting
-- with a key, but a top-level table does not have a key, so we must
-- use the lower level 'Toml.parse' and 'Toml.tomlTables' before
-- repeatedly applying the provided 'Toml.TomlCodec'.
parseFileOf :: forall a. Toml.TomlCodec a -> T.Text -> Either [T.Text] [(T.Text, a)]
parseFileOf codec =
first (map Toml.prettyTomlDecodeError)
. validationToEither
. traverse (uncurry go)
. Toml.toList
. Toml.tomlTables
. either (error . show) id
. Toml.parse
where
go :: Toml.Key -> Toml.TOML -> Validation [Toml.TomlDecodeError] (T.Text, a)
go k v = (keyText k,) <$> Toml.runTomlCodec codec v
This TOML
is equivalent to this JSON
This data maps cleanly to this Haskell representation
However, I cannot figure out how to parse this shape of data with
tomland
. I threw together a quick repo to demonstrate my attempts and problems. The exact errors are in the CI run. I'm not sure if I'm misunderstanding how the library is supposed to be used, or if this sort of data is simply not able to be parsed by it currently.Additionally, Map1 fails to decode the data that it just encoded. I'm not sure why that is, or if it's something I'm missing or a bug in the library. Map3, which should work from my understanding, also has curious behavior in regard to parsing equivalent TOML files differently (in particular, one being an error with the
-Exact
decoding variants).