traverse
превращает вещи внутри Traversable
в Traversable
вещей "внутри" Applicative
, учитывая функцию, которая делает Applicative
из вещей.
Давайте использовать Maybe
как Applicative
и список Traversable
.Сначала нам понадобится функция преобразования:
half x = if even x then Just (x `div` 2) else Nothing
Итак, если число четное, мы получаем половину его (внутри Just
), иначе мы получим Nothing
.Если все идет «хорошо», это выглядит так:
traverse half [2,4..10]
--Just [1,2,3,4,5]
Но ...
traverse half [1..10]
-- Nothing
Причина в том, что для построения результата используется функция <*>
,и когда один из аргументов равен Nothing
, мы получаем Nothing
назад.
Другой пример:
rep x = replicate x x
Эта функция генерирует список длины x
с содержимым x
, например rep 3
= [3,3,3]
.Каков результат traverse rep [1..3]
?
Мы получаем частичные результаты [1]
, [2,2]
и [3,3,3]
, используя rep
.Теперь семантика списков как Applicatives
- «взять все комбинации», например, (+) <$> [10,20] <*> [3,4]
- [13,14,23,24]
.
«Все комбинации» из [1]
и [2,2]
дважды [1,2]
.Все комбинации по два раза [1,2]
и [3,3,3]
шесть раз [1,2,3]
.Итак, имеем:
traverse rep [1..3]
--[[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]