Наконец разбор без тегов и рекурсивные монадические действия

Я десериализирую структуру данных с диска в окончательно без тегов стиле. т.е.

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

Важным шагом является то, что он будет поставлять дополнительный загрузчик параметров для нового parseOnlyd SYM Repl, таким образом, выбирая правильный экземпляр.

Полный фрагмент находится в аннотированной лямбда-вставке: http://lpaste.net/105182. проверить это с помощью ввода "включить токен"

Другие вопросы по тегам