Replies (16)
-
@Macil, я к сожалению не очень понял вопрос, т.е. видимо у тебя что-то вроде `Zipper a = (Info-about-structure, zipCont Structure -> a)`?
и на основе этого ты хочешь строить сложные zipper-ы используя тайпклассы Applicative, Alternative, Monad. Я не очень понимаю как это будет работать (это не значит, что то, что предложено плохо), просто я не вижу всей ситуации./9 · Reply -
@qnikst, Представь себе самый обычный комбинаторный парсер типа attoparsec или парсера из aeson/binary/cereal. Они определены в continuation-форме Input -> Failure -> Success -> Result, где Failure и Success — функции в форме Input -> ... -> Result (упрощенно).
Обычно в качестве Input применяется список или какой-нибудь stream или еще чего-нибудь что позволяет эффективно взять «слеудющий» токен и вернуть «остаток».
Я же хочу в качесте Input использовать Zipper, т.е. можно будет написать left > right > right что будет равно композиции соответствующих операций для зиппера... Т.е. можно спокойно таскаться по дереву туда-сюда ради своих целей.
Поскольку XML-дерево будет задано в FCNS-форме, то навигация будет достаточно специфичной, но передельно простой и главное интуитивно понятной.
Строго говоря, для такого парсера даже не нужно идти «вверх», но мне всё-равно нужно фокусироваться на конкретном XML-узле, так что зиппер в любом случае будет.
Вот собственно, вопрос, а стоит ли это вообще затевать... Например, Э. Кметт в своём пакете Control.Zippers (Control.Zipper, убранный из пакета lens) предлагает несколько иной подход. -
@Macil, смотри, я zipper это бегалка по структуре + набор функций, соотвественно все перемещение это их композиция, типа
```
zipper structure & left
& right
& delete
& insert 17
& commit
```
здесь мы написали большую композицию фунций где мы создаем зиппер идём влево, вправо, удаляем ноду, вставляем на её место другую и коммитим получившуюся структуру.
Вроде все просто и наглядно.
при этом (я так сходу не умею) если таскаться с каком-нибудь Funtor/Applicative как делается в линзах, о ещё и благодаря эффектам можно протащить аккумулятор например. -
@qnikst, Вот вот. И не столько аккумулятор, сколько возможность «фейлить» и комбинатор <|> для работы с фейлами, плюс возможность использовать аппликативный стиль
```
<Foo a="a" b="b">
<Bar>Bar</Bar>
</Foo>
```
```
Foo <$> (tag "Foo" *> attribute "a")
<*> (attribute "b")
<> (left > tag "Bar" > left > text < upleft < upleft)
```
Точную семантику комбинаторов пока определить сложно, так что написал с неспрятанной внутрь навигацией по дереву.
Если говорить языком mtl, то это комбинация ExceptT и StateT. State протаскивает зиппер через комбинаторы, а ExceptT управляет управляет вычислимостью «следующего» комбинатора.