Расширение одного объектива Traversal с другим объективом Traversal - PullRequest
0 голосов
/ 15 января 2020

Допустим, у меня есть узел, и у него могут быть дети, братья и сестры, и у меня есть реализации линз обхода для них. Как мне объединить их в одну линзу, которая пересекает как детей, так и братьев и сестер?

_children :: Traversal' Node Node
_children = ...

_siblings :: Traversal' Node Node
_siblings = ...

_relatives :: Traversal' Node Node
_relatives = ???

Похоже на очень простой c вопрос, но я не смог найти никакой информации о том, как "добавить" один обход к другому.

1 Ответ

0 голосов
/ 15 января 2020

Это самое близкое, что у меня есть, используя функцию wander:

_relatives :: Traversal' Node Node
_relatives = wander tra
  where
  tra1 :: forall f. Applicative f => (Node -> f Node) -> Node → f Node
  tra1 = traverseOf _children

  tra2 :: forall f. Applicative f => (Node -> f Node) -> Node → f Node
  tra2 = traverseOf _siblings

  tra :: forall f. Applicative f => (Node -> f Node) -> Node → f Node
  tra g w = lift2 combine fw' fw''
    where
    fw' = tra1 g w

    fw'' = tra2 g w

    combine (Node w') (Node w'') = Node (w' { siblings = w''.siblings })

Если бы я только мог избавиться от этой последней строки ...

combine (Node w') (Node w'') = Node (w' { siblings = w''.siblings })

В идеале , мой tra будет выглядеть так (результат объединения tra1 в tra2):

tra :: forall f. Monad f => (Node -> f Node) -> Node -> f Node
tra g w = tra2 g =<< tra1 g w

Но я не могу этого сделать, потому что wander запрашивает ограничение Applicative и не Monad. И я не могу связать в цепочку результаты Applicative.

Я также могу сделать это в общем случае, если мои Node реализуют Semigroup:

tra :: forall f. Applicative f => (Node -> f Node) -> Node -> f Node
tra g w = lift2 append fw' fw''
  where
  fw' = tra1 g w
  fw'' = tra2 g w

Но у меня нет Semigroup для моего реального варианта использования ...

Неужели нет универсального c способа объединить два обхода?

Я действительно надеюсь, что кто-то может придумать лучший подход. Если нет, я отмечу этот ответ как принятый через некоторое время.

РЕДАКТИРОВАТЬ:

Оказывается, я не единственный, кто хочет это сделать, и по-видимому, это невозможно из-за «последовательности» природы такого преобразования - для этого требуется монада, в то время как у нас есть только аппликативный https://github.com/ekmett/lens/issues/109

Собираюсь принять этот ответ, поскольку, вероятно, нет лучшего ответ, чем "нет ответа".

...