3

我以最终无标签样式反序列化磁盘中的数据结构。IE

class SYM repl where
    a :: repl
    include :: FilePath -> repl 

myParser :: SYM r => Parser r

我正在解析的语言包含指令。

我使用attoparsec的不是单子变压器,所以我不能简单地提供一个类型Loader = FilePath -> IO (Maybe Text)

我可以用以下SYM实例编写一个解释器,它解决了一个包含问题。

instance SYM r => SYM (Loader -> IO (Either String r)) where
    include path loader = 
        maybe (Left "cannot load") (parseOnly myParser) <$> loader path

不幸的是,包含在包含文件中的内容没有得到解决。当然我可以解决它们两次以解决下一层。但是,如果我想对每个可能的级别都这样做,那会导致无限类型。

现在我预加载所有包含(在 a 中HashMap)并绑定它们,所以我可以将 a 传递FilePath -> Maybe Text给解析器并在那里解析包含,但这显然不是最佳的。(并且 includeSYM不再是其中的一部分。)

我的问题是,最终无标签样式如何处理该问题?

编辑:我在 lpaste 上发布了一个完整的例子:http: //lpaste.net/105182

4

1 回答 1

1

事后看来这很容易,但通常是这样。

仅一级解析如下。

instance SYM r => SYM (Loader -> IO (Either String r)) where
    token t _ = return . Right $ token t
    include path loader =
        maybe (Left "cannot load") (parseOnly myParser) <$> loader path

即它将parseOnly myParser :: Either String r在(成功)加载的文件上运行。

resolve-everything 只需要选择SYM (Loader -> IO (Either String r))实例myParser并添加loader参数:

    include path loader =
        maybe (return $ Left "cannot load")
              (either (return ∘ Left) ($ loader) . parseOnly myParser)
              =<< loader path

关键步骤是它将为新的parseOnlyd SYMrepl 提供附加参数加载器,从而选择正确的实例。

完整的片段在带注释的 lambda 粘贴中:http: //lpaste.net/105182。输入“包括包含令牌”对其进行测试

于 2014-06-09T20:37:47.473 回答