Я хотел бы отметить, что в вашем исходном коде []
и Maybe
являются избыточными, и что более тщательное изучение значения этих двух функторов приводит к интересному обсуждению. []
(список) представляет успех или неудачу в том же смысле, что и Maybe
, главное отличие в том, что []
может представлять 0 или более значений, тогда как Maybe
ограничено значением 0 или 1.
Это приводит к другому рассуждению о значении Just
в Just 2
. Что означает, что 2
будет заключено в Just
, и что будет означать Nothing
? Чтобы продвинуться на один шаг вперед, вот пять различных результатов, которые вы можете выбрать, каждый из которых имеет различное значение:
Just [3, 4]
: было одно монолитное вычисление, которое работало с несколькими значениями, и оноудалось. Nothing
: могло быть монолитное значение, но его нет. [3, 4]
: был пакет вычислений, и это значения, которые были получены. []
: могло быть несколько значений, но их нет. [Just 3, Just 4]
: был пакет вычислений, где каждое вычисление могло завершиться неудачей, и всеони успешно выполнены.
Случай 1 : если h
представляет монолитное значение и является уникальной точкой отказа в этой цепочке вычислений, то варианты 1 и 2 выглядят какразумный выбор. Следующий код выполняет это:
import Control.Applicative (LiftA2)
h = Just 2
add = (+)
addH = LiftA2 add h . pure
-- Returns Just [3,4] or Nothing
mainFunc = traverse addH [1,2]
Случай 2 : если add
представляет функцию, которая может завершиться ошибкой в зависимости от ее аргумента (например, представьте функцию hDivBy
,что не сработает при каждом 0), тогда варианты 3 и 4 кажутся хорошим выбором.
import Data.Maybe (mapMaybe)
hDivBy = \x -> (`div` x) <$> h
--Returns [1]
mainFunc = mapMaybe hDivBy [0, 2]
Случай 3 : Если вы хотите отслеживать индексацию элементов, то вариант 5 даст вам следующее:
--Returns [Nothing, Just 2]
mainFunc = fmap hDivBy [0,2]
Обратите внимание, что этот кодсохраняет все в Applicative
царстве, делая его более общим, среди других преимуществ .