Наконец разбор без тегов и рекурсивные монадические действия
Я десериализирую структуру данных с диска в окончательно без тегов стиле. т.е.
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
к сожалению, включение во включенный файл не разрешается. конечно, я могу разрешить их дважды, чтобы разрешить следующий слой. но это приводит к бесконечным типам, если я хочу сделать это для каждого возможного уровня.
Прямо сейчас я предварительно загрузить все включает (в HashMap
) и связать их, чтобы я мог передать FilePath -> Maybe Text
для синтаксического анализа и разрешения включает в себя, но это явно не оптимально. (и включать не является частью SYM
больше.)
мой вопрос, как стиль без тегов решает эту проблему?
редактировать: я опубликовал полный пример на lpaste: http://lpaste.net/105182
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
в (успешно) загруженном файле.
Решить все нужно будет просто выбрать SYM (Loader -> IO (Either String r))
экземпляр для myParser
и добавить loader
аргумент:
include path loader =
maybe (return $ Left "cannot load")
(either (return ∘ Left) ($ loader) . parseOnly myParser)
=<< loader path
Важным шагом является то, что он будет поставлять дополнительный загрузчик параметров для нового parseOnly
d SYM
Repl, таким образом, выбирая правильный экземпляр.
Полный фрагмент находится в аннотированной лямбда-вставке: http://lpaste.net/105182. проверить это с помощью ввода "включить токен"