Data.Yaml
のパーサーコンビネーターの作り方について質問です
decodeFileEither
などで読み込んだYamlの中にあるパスをさらに読み込んでパースがしたいのですが、一度他の型を経由させる方法しか思いつかなくて迷っています。
パーサー(`Parser a` )内部でIOを使うことは可能でしょうか(パース結果をFilePathとして、そのファイルも読みにいくことは可能でしょうか)
runParser
内部にある
f
がどうにかできないのかなと思っているのですがよくわからず…
何かいい方法があれば知りたいです…
例としては:
data:
- path: foo.yaml
offset: (0, 1)
...
というファイルを
decodeFileEither
で読んだ時、`foo.yaml` も読み込んで結果に含めたいです。
現在は一度しか入れ子にならないため、一つ中間用の型を用意してその型に(パスはStringとして保存して)変換した後、その中にしまったパスをさらに
decodeFileEither
で読んでいます。
data ActualData = ActuallData ...
data IntermediateData = IntermidiateData { path :: FilePath, ... }
load :: FilePath -> IO (Either ParseException ActualData)
load fp = do
intermediate <- decodeFileEither fp
includedData <- decodeFileEither $ path intermediate
return -- intermediate と includedData を使用して、ActualData を生成する
実際に使っている例だとこれになります。(
Face
をデコードするために、一度
FaceFile
としてデコードした後に読み直している)
https://github.com/Cj-bc/faclig/blob/master/src/Graphics/Asciiart/Faclig/Types.hs#L36-L57しかし、
• 途中に他の型をできれば挟みたくない
• 入れ子を何重にもしたいので、一度で解決できるようにしたい
という理由があり、なんとかできないのかなと悩んでいます。