diff --git a/src/Data/Array/NonEmpty/Internal.js b/src/Data/Array/NonEmpty/Internal.js index 0971fc45..40d88a75 100644 --- a/src/Data/Array/NonEmpty/Internal.js +++ b/src/Data/Array/NonEmpty/Internal.js @@ -1,6 +1,16 @@ "use strict"; -exports.fold1Impl = function (f) { +exports.foldr1Impl = function (f) { + return function (xs) { + var acc = xs[xs.length - 1]; + for (var i = xs.length - 2; i >= 0; i--) { + acc = f(xs[i])(acc); + } + return acc; + }; +}; + +exports.foldl1Impl = function (f) { return function (xs) { var acc = xs[0]; var len = xs.length; diff --git a/src/Data/Array/NonEmpty/Internal.purs b/src/Data/Array/NonEmpty/Internal.purs index 1603bd05..3d87a69e 100644 --- a/src/Data/Array/NonEmpty/Internal.purs +++ b/src/Data/Array/NonEmpty/Internal.purs @@ -35,7 +35,9 @@ derive newtype instance foldableWithIndexNonEmptyArray :: FoldableWithIndex Int instance foldable1NonEmptyArray :: Foldable1 NonEmptyArray where foldMap1 = foldMap1Default - fold1 = fold1Impl (<>) + fold1 = foldl1Impl (<>) + foldr1 = foldr1Impl + foldl1 = foldl1Impl derive newtype instance unfoldable1NonEmptyArray :: Unfoldable1 NonEmptyArray derive newtype instance traversableNonEmptyArray :: Traversable NonEmptyArray @@ -56,7 +58,8 @@ derive newtype instance monadNonEmptyArray :: Monad NonEmptyArray derive newtype instance altNonEmptyArray :: Alt NonEmptyArray -- we use FFI here to avoid the unncessary copy created by `tail` -foreign import fold1Impl :: forall a. (a -> a -> a) -> NonEmptyArray a -> a +foreign import foldr1Impl :: forall a. (a -> a -> a) -> NonEmptyArray a -> a +foreign import foldl1Impl :: forall a. (a -> a -> a) -> NonEmptyArray a -> a foreign import traverse1Impl :: forall m a b diff --git a/test/Test/Data/Array/NonEmpty.purs b/test/Test/Data/Array/NonEmpty.purs index fbc576fa..5ac15de5 100644 --- a/test/Test/Data/Array/NonEmpty.purs +++ b/test/Test/Data/Array/NonEmpty.purs @@ -10,7 +10,7 @@ import Data.FunctorWithIndex (mapWithIndex) import Data.Maybe (Maybe(..), fromJust) import Data.Monoid.Additive (Additive(..)) import Data.NonEmpty ((:|)) -import Data.Semigroup.Foldable (foldMap1) +import Data.Semigroup.Foldable (foldMap1, foldr1, foldl1) import Data.Semigroup.Traversable (traverse1) import Data.Tuple (Tuple(..)) import Data.Unfoldable1 as U1 @@ -297,12 +297,22 @@ testNonEmptyArray = do log "Unfoldable instance" assert $ U1.range 0 9 == NEA.range 0 9 - log "foldl should work" + log "foldMap1 should work" + assert $ foldMap1 Additive (fromArray [1, 2, 3, 4]) == Additive 10 + + log "fold1 should work" -- test through sum assert $ sum (fromArray [1, 2, 3, 4]) == 10 - log "foldMap1 should work" - assert $ foldMap1 Additive (fromArray [1, 2, 3, 4]) == Additive 10 + log "foldr1 should work" + assert $ foldr1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a", "b", "c", "d"]) == "(a(b(cd)))" + assert $ foldr1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a", "b"]) == "(ab)" + assert $ foldr1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a"]) == "a" + + log "foldl1 should work" + assert $ foldl1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a", "b", "c", "d"]) == "(((ab)c)d)" + assert $ foldl1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a", "b"]) == "(ab)" + assert $ foldl1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a"]) == "a" log "traverse1 should work" assert $ traverse1 Just (fromArray [1, 2, 3, 4]) == NEA.fromArray [1, 2, 3, 4]