Давайте начнем с более знакомого примера: использование S.reduce
в массиве.
> S.reduce (acc => s => acc + s) ('initial:') (['foo', 'bar', 'baz'])
'initial:foobarbaz'
Теперь давайте специализируемся на типе S.reduce
, чтобы объяснить поведение выше.
S.reduce :: Foldable f => (b -> a -> b) -> b -> f a -> b
-- replace ‘Foldable f => f’ with ‘Array’ --
S.reduce :: (b -> a -> b) -> b -> Array a -> b
Далее, давайте специализируемся на типе S.reduce
, чтобы увидеть, как он будет работать с любыми значениями.
S.reduce :: Foldable f => (b -> a -> b) -> b -> f a -> b
-- replace ‘Foldable f => f’ with ‘Either x’ --
S.reduce :: (b -> a -> b) -> b -> Either x a -> b
Что мы можем сделать, если дать S.Left ('foo')
как Either x a
? У нас есть x
('foo'
), но нет a
. Поскольку у нас нет a
, мы не можем использовать функцию b -> a -> b
. Таким образом, единственное b
, которое мы можем вернуть, - это начальное значение.
> S.reduce (acc => s => acc + s) ('initial:') (S.Left ('foo'))
'initial:'
Что мы можем сделать, если дать S.Right ('bar')
как Either x a
? У нас есть a
, который мы можем передать функции b -> a -> b
вместе с начальным значением, чтобы получить другое значение типа b
.
> S.reduce (acc => s => acc + s) ('initial:') (S.Right ('bar'))
'initial:bar'
Если бы S.reduce
должен был вернуть 'initial:'
или 'initial:bar:bar:bar'
в вышеприведенном случае, он все равно соответствовал бы сигнатуре типа, но реализация fantasy-land/reduce
для типа Любой из Sanctuary применяет функцию ровно один раз, когда ей дают Право .