diff --git a/CHANGELOG.md b/CHANGELOG.md index 22d8f97..1bb9aab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Breaking changes: - Migrate FFI to ES modules (#37 by @kl0tl and @JordanMartinez) New features: +- Add `iterateN` function (#20 by @matthewleon and @JordanMartinez) Bugfixes: diff --git a/src/Data/Unfoldable.purs b/src/Data/Unfoldable.purs index 68930a1..fd115c1 100644 --- a/src/Data/Unfoldable.purs +++ b/src/Data/Unfoldable.purs @@ -18,7 +18,7 @@ import Prelude import Data.Maybe (Maybe(..), isNothing, fromJust) import Data.Traversable (class Traversable, sequence) import Data.Tuple (Tuple(..), fst, snd) -import Data.Unfoldable1 (class Unfoldable1, unfoldr1, singleton, range, replicate1, replicate1A) +import Data.Unfoldable1 (class Unfoldable1, unfoldr1, singleton, range, iterateN, replicate1, replicate1A) import Partial.Unsafe (unsafePartial) -- | This class identifies (possibly empty) data structures which can be diff --git a/src/Data/Unfoldable1.purs b/src/Data/Unfoldable1.purs index 6e4667b..2eb285b 100644 --- a/src/Data/Unfoldable1.purs +++ b/src/Data/Unfoldable1.purs @@ -4,6 +4,7 @@ module Data.Unfoldable1 , replicate1A , singleton , range + , iterateN ) where import Prelude @@ -111,3 +112,20 @@ range start end = go delta i = let i' = i + delta in Tuple i (if i == end then Nothing else Just i') + +-- | Create an `Unfoldable1` by repeated application of a function to a seed value. +-- | For example: +-- | +-- | ``` purescript +-- | (iterateN 5 (_ + 1) 0 :: Array Int) == [0, 1, 2, 3, 4] +-- | (iterateN 5 (_ + 1) 0 :: NonEmptyArray Int) == NonEmptyArray [0, 1, 2, 3, 4] +-- | +-- | (iterateN 0 (_ + 1) 0 :: Array Int) == [0] +-- | (iterateN 0 (_ + 1) 0 :: NonEmptyArray Int) == NonEmptyArray [0] +-- | ``` +iterateN :: forall f a. Unfoldable1 f => Int -> (a -> a) -> a -> f a +iterateN n f s = unfoldr1 go $ Tuple s (n - 1) + where + go (Tuple x n') = Tuple x + if n' > 0 then Just $ Tuple (f x) $ n' - 1 + else Nothing diff --git a/test/Main.purs b/test/Main.purs index ef38e80..c39d640 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -61,6 +61,9 @@ main = do assert $ U1.range 0 0 == NonEmpty 0 [] assert $ U1.range 0 2 == NonEmpty 0 [1, 2] + log "Test iterateN" + assert $ U.iterateN 5 (_ + 1) 0 == [0, 1, 2, 3, 4] + log "Test Maybe.toUnfoldable" assert $ U.fromMaybe (Just "a") == ["a"] assert $ U.fromMaybe (Nothing :: Maybe String) == []