2014-05-23 3 views
5

В Control.Lens.Traversal функция beside пересекает обе части Bitraversable. Приведенный пример являетсяКак я могу отслеживать разные части структуры данных один за другим?

>>> ("hello",["world","!!!"])^..beside id traverse 
["hello","world","!!!"] 

Могу ли я написать более явную версию beside (назовем его bothParts), что вместо Bitraversable ограничение имеет два Traversal сек? Я полагаю, что это должно использоваться так:

Это уже существует? Является ли это слишком опасным для использования в здравом смысле? Спасибо!

Edit:

Или, возможно, что-то вроде:

>>> ("hello",["world","!!!"])^..bothParts _1 (_2.traverse) 
["hello","world","!!!"] 
+2

Я думаю, что 'bothParts l1 l2' не всегда будет действительным' Traversal'. Рассмотрим 'bothParts _1 _1' (или любой другой случай, когда' l1' и 'l2' перекрываются). – fizruk

ответ

2

комбинатора вы хотите, как предполагается использовать 2 Traversal s одновременно. Но такой комбинатор нарушает законы вообще, в частности закон «нет дублирования»: a Traversal должен пересекать каждый элемент только один раз.

Вот пример того, что вы, вероятно, не хотите:

>>> (1, 2) ^.. bothParts _1 _1 
[1, 1]  

Чтобы быть более точным, я хотел бы процитировать Traversal documentation from lens package:

Законов для более Traversal t следует из законы для Traversable, как указано в "The Essence of the Iterator Pattern".

t pure ≡ pure 
fmap (t f) . t g ≡ getCompose . t (Compose . fmap f . g) 

Одним из следствий этого требования является то, что Traversal потребности оставить одинаковое количество элементов в качестве кандидата для последующего Traversal, что она началась с. Еще одним свидетельством силы этих законов является то, что оговорка, выраженная в разделе 5.5 «Сущности шаблона итератора» об экзотических случаях, которые пересекали одну и ту же запись несколько раз, на самом деле уже была исключена вторым законом в той же самой статье!

+0

Хорошо, да, спасибо, но если я обещаю всегда пересекать разные подчасти, как бы написать такую ​​функцию? – phischu

+0

@phischu в вашем вопросе вы используете только 'Traversal' как 'Fold's ', поэтому, возможно, вам будет достаточно использовать [' ReifiedFold'] (https://hackage.haskell.org/package/lens-4.1. 2/docs/Control-Lens-Reified.html # t: ReifiedFold) для создания разных 'Fold', например: '(" hello ", [" world "," !!! "])^.. runFold (Fold _1 <|> Fold (_2.traverse)) ' – fizruk

+0

Этого не достаточно, но спасибо! – phischu