Skip to content

Commit 813147c

Browse files
committed
NonEmptyArray: Unfoldable1 support
Will amend bower.json after merge of purescript/purescript-nonempty#29
1 parent 8058d49 commit 813147c

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

bower.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@
1717
],
1818
"dependencies": {
1919
"purescript-foldable-traversable": "^3.3.0",
20-
"purescript-nonempty": "^4.0.0",
2120
"purescript-partial": "^1.2.0",
2221
"purescript-st": "^3.0.0",
2322
"purescript-tailrec": "^3.0.0",
2423
"purescript-tuples": "^4.0.0",
25-
"purescript-unfoldable": "^3.0.0",
26-
"purescript-unsafe-coerce": "^3.0.0"
24+
"purescript-unsafe-coerce": "^3.0.0",
25+
"purescript-nonempty": "^4.3.0"
2726
},
2827
"devDependencies": {
2928
"purescript-assert": "^3.0.0",

src/Data/Array/NonEmpty.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@ exports.fold1Impl = function (f) {
1111
};
1212
};
1313

14+
exports.unfoldr1Impl = function (isNothing) {
15+
return function (fromJust) {
16+
return function (fst) {
17+
return function (snd) {
18+
return function (f) {
19+
return function (value) {
20+
var result = [];
21+
while (true) { // eslint-disable-line no-constant-condition
22+
var tuple = f(value);
23+
result.push(fst(tuple));
24+
var maybe = snd(tuple);
25+
if (isNothing(maybe)) return result;
26+
value = fromJust(maybe); // eslint-disable-line no-param-reassign
27+
}
28+
};
29+
};
30+
};
31+
};
32+
};
33+
};
34+
1435
exports.traverse1Impl = function () {
1536
function Cont(fn) {
1637
this.fn = fn;

src/Data/Array/NonEmpty.purs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module Data.Array.NonEmpty
88
, fromFoldable
99
, fromFoldable1
1010
, toUnfoldable
11+
, toUnfoldable1
1112
, singleton
1213
, (..), range
1314
, replicate
@@ -103,15 +104,16 @@ import Data.Eq (class Eq1)
103104
import Data.Foldable (class Foldable)
104105
import Data.FoldableWithIndex (class FoldableWithIndex)
105106
import Data.FunctorWithIndex (class FunctorWithIndex)
106-
import Data.Maybe (Maybe(..), fromJust)
107+
import Data.Maybe (Maybe(..), fromJust, isNothing)
107108
import Data.NonEmpty (NonEmpty, (:|))
108109
import Data.Ord (class Ord1)
109110
import Data.Semigroup.Foldable (class Foldable1, foldMap1Default)
110111
import Data.Semigroup.Traversable (class Traversable1, sequence1Default)
111112
import Data.Traversable (class Traversable)
112113
import Data.TraversableWithIndex (class TraversableWithIndex)
113-
import Data.Tuple (Tuple)
114+
import Data.Tuple (Tuple(..), fst, snd)
114115
import Data.Unfoldable (class Unfoldable)
116+
import Data.Unfoldable1 (class Unfoldable1, unfoldr1)
115117
import Partial.Unsafe (unsafePartial)
116118

117119
newtype NonEmptyArray a = NonEmptyArray (Array a)
@@ -137,6 +139,9 @@ instance foldable1NonEmptyArray :: Foldable1 NonEmptyArray where
137139
foldMap1 = foldMap1Default
138140
fold1 = fold1Impl (<>)
139141

142+
instance unfoldable1NonEmptyArray :: Unfoldable1 NonEmptyArray where
143+
unfoldr1 = unfoldr1Impl isNothing (unsafePartial fromJust) fst snd
144+
140145
derive newtype instance traversableNonEmptyArray :: Traversable NonEmptyArray
141146
derive newtype instance traversableWithIndexNonEmptyArray :: TraversableWithIndex Int NonEmptyArray
142147

@@ -154,6 +159,16 @@ derive newtype instance monadNonEmptyArray :: Monad NonEmptyArray
154159

155160
derive newtype instance altNonEmptyArray :: Alt NonEmptyArray
156161

162+
foreign import unfoldr1Impl
163+
:: forall a b
164+
. (forall x. Maybe x -> Boolean)
165+
-> (forall x. Maybe x -> x)
166+
-> (forall x y. Tuple x y -> x)
167+
-> (forall x y. Tuple x y -> y)
168+
-> (b -> Tuple a (Maybe b))
169+
-> b
170+
-> NonEmptyArray a
171+
157172
-- | Internal - adapt an Array transform to NonEmptyArray
158173
--
159174
-- Note that this is unsafe: if the transform returns an empty array, this can
@@ -200,6 +215,13 @@ fromFoldable1 = unsafeFromArray <<< A.fromFoldable
200215
toUnfoldable :: forall f a. Unfoldable f => NonEmptyArray a -> f a
201216
toUnfoldable = adaptAny A.toUnfoldable
202217

218+
toUnfoldable1 :: forall f a. Unfoldable1 f => NonEmptyArray a -> f a
219+
toUnfoldable1 xs = unfoldr1 f 0
220+
where
221+
len = length xs
222+
f i = Tuple (unsafePartial unsafeIndex xs i) $
223+
if i < (len - 1) then Just (i + 1) else Nothing
224+
203225
singleton :: forall a. a -> NonEmptyArray a
204226
singleton = NonEmptyArray <<< A.singleton
205227

test/Test/Data/Array/NonEmpty.purs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ import Prelude
44

55
import Control.Monad.Eff (Eff)
66
import Control.Monad.Eff.Console (CONSOLE, log)
7+
import Data.Array as A
78
import Data.Array.NonEmpty as NEA
89
import Data.Const (Const(..))
910
import Data.Foldable (for_, sum, traverse_)
1011
import Data.FunctorWithIndex (mapWithIndex)
1112
import Data.Maybe (Maybe(..), fromJust)
1213
import Data.Monoid.Additive (Additive(..))
14+
import Data.NonEmpty ((:|))
1315
import Data.Semigroup.Foldable (foldMap1)
1416
import Data.Semigroup.Traversable (traverse1)
1517
import Data.Tuple (Tuple(..))
18+
import Data.Unfoldable1 as U1
1619
import Partial.Unsafe (unsafePartial)
1720
import Test.Assert (ASSERT, assert)
1821

@@ -285,6 +288,12 @@ testNonEmptyArray = do
285288
, fromArray [4,0,0,1,25,36,458,5842,23757]
286289
])
287290

291+
log "toUnfoldable1"
292+
assert $ NEA.toUnfoldable1 (NEA.range 0 9) == 0 :| A.range 1 9
293+
294+
log "Unfoldable instance"
295+
assert $ U1.range 0 9 == NEA.range 0 9
296+
288297
log "foldl should work"
289298
-- test through sum
290299
assert $ sum (fromArray [1, 2, 3, 4]) == 10

0 commit comments

Comments
 (0)