Почему "отказ" (от объектива) приводит к недействительным обходам?

Из документации:

Попробуйте первый Traversal (или Fold), возвращаясь ко второму Traversal (или Fold), если он не возвращает никаких записей.

Это только допустимый Traversal, если второй Traversal не пересекается с результатом первого или возвращает точно такие же результаты.

Есть ли простой пример неверного обхода, сгенерированного failing, и тестовый пример, демонстрирующий его?

Ответы

Ответ 1

Для контрпримера сначала определим новый тип данных, для которого мы генерируем обходы с помощью makePrisms:

data T = A T | C deriving Show
makePrisms ''T

_A :: Traversal T T теперь является допустимым обходом. Теперь создайте новый обход с помощью failing:

t :: Traversal' T T
t = failing _A id

Обратите внимание, что (C & t .~ A C) ^.. t = [C], похоже, что он не прошел закон обхода (вы не получаете то, что вы положили). Действительно, второй закон обхода:

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

что не выполняется, как видно из следующего выбора для f и g:

-- getConst . t f = toListOf t
f :: T -> Const [T] T
f = Const . (:[])

-- runIdentity . t g = t .~ A C
g :: T -> Identity T
g = pure . const (A C)

Тогда:

> getConst . runIdentity . fmap (t f) . t g $ C
[C]

В то время как:

> getConst . runIdentity . getCompose . t (Compose . fmap f . g) $ C
[A C]

Таким образом, действительно существует случай, когда failing с допустимыми обходами не приводит к допустимому обходу.