Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Objects aka dictionaries as Traversables #3448

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 30 additions & 7 deletions source/sequence.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import map from './map.js';
import prepend from './prepend.js';
import reduceRight from './reduceRight.js';
import identity from './internal/_identity.js';
import _isArray from './internal/_isArray.js';
import toPairs from './toPairs.js';
import _assoc from './internal/_assoc.js';


/**
* Transforms a [Traversable](https://github.com/fantasyland/fantasy-land#traversable)
* of [Applicative](https://github.com/fantasyland/fantasy-land#applicative) into an
* Applicative of Traversable.
*
* Also accepts `Object` as the Traversable to aid working with [dictionaries](https://github.com/ramda/ramda/wiki/Type-Signatures#simple-objects) (Objects of like-typed values).
*
* Dispatches to the `"fantasy-land/traverse"` or the `traverse` method of the second argument, if present.
*
* @func
Expand All @@ -29,6 +34,8 @@ import identity from './internal/_identity.js';
* R.sequence(Maybe.of, [Just(1), Just(2), Just(3)]); //=> Just([1, 2, 3])
* R.sequence(Maybe.of, [Just(1), Just(2), Nothing()]); //=> Nothing()
*
* R.sequence(Maybe.of, {a: Just(1), b: Just(2), c: Just(3)}); //=> Just({a: 1, b: 2, c: 3})
*
* R.sequence(R.of(Array), Just([1, 2, 3])); //=> [Just(1), Just(2), Just(3)]
* R.sequence(R.of(Array), Nothing()); //=> [Nothing()]
*/
Expand All @@ -45,13 +52,29 @@ var sequence = _curry2(function sequence(F, traversable) {
? traversable['fantasy-land/traverse'](TypeRep, identity)
: typeof traversable.traverse === 'function'
? traversable.traverse(TypeRep, identity)
: reduceRight(
function(x, acc) {
return ap(map(prepend, x), acc);
},
of([]),
traversable
)
: _isArray(traversable)
? reduceRight(
function(x, acc) {
return ap(map(prepend, x), acc);
},
of([]),
traversable
)
: reduceRight(
function(kvPair, acc) {
return ap(map(
function(v) {
return function(obj) {
return _assoc(kvPair[0], v, obj);
};
},
kvPair[1]
),
acc);
},
of({}),
toPairs(traversable)
)
);
});
export default sequence;
4 changes: 4 additions & 0 deletions source/traverse.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import sequence from './sequence.js';
*
* Dispatches to the `traverse` method of the third argument, if present.
*
* Also accepts `Object` as the Traversable to aid working with [dictionaries](https://github.com/ramda/ramda/wiki/Type-Signatures#simple-objects) (Objects of like-typed values).
*
* @func
* @memberOf R
* @since v0.19.0
Expand All @@ -31,6 +33,8 @@ import sequence from './sequence.js';
* R.traverse(Maybe.of, safeDiv(10), [2, 4, 5]); //=> Maybe.Just([5, 2.5, 2])
* R.traverse(Maybe.of, safeDiv(10), [2, 0, 5]); //=> Maybe.Nothing
*
* R.traverse(Maybe.of, safeDiv(10), {a: 2, b: 4}); //=> Maybe.Just({a: 5, b: 2.5})
*
* // Using a Type Representative
* R.traverse(Maybe, safeDiv(10), Right(4)); //=> Just(Right(2.5))
* R.traverse(Maybe, safeDiv(10), Right(0)); //=> Nothing
Expand Down
5 changes: 5 additions & 0 deletions test/sequence.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ describe('sequence', function() {
eq(R.sequence(ofMaybe, [Just(3), Nothing, Just(5)]), Nothing);
});

it('operates on a dictionary of applicatives', function() {
eq(R.sequence(ofMaybe, {a: Just(3), b: Just(4), c: Just(5)}), Just({a: 3, b: 4, c: 5}));
eq(R.sequence(ofMaybe, {a: Just(3), b: Nothing, c: Just(5)}), Nothing);
});

it('traverses left to right', function() {
eq(R.sequence(ofEither, [Right(1), Right(2)]), Right([1, 2]));
eq(R.sequence(ofEither, [Right(1), Left('XXX')]), Left('XXX'));
Expand Down
5 changes: 5 additions & 0 deletions test/traverse.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ describe('traverse', function() {
eq(R.traverse(ofMaybe, R.map(R.add(10)), [Just(3), Nothing, Just(5)]), Nothing);
});

it('operates on a dictionary of applicatives', function() {
eq(R.traverse(ofMaybe, R.map(R.add(10)), {a: Just(3), b: Just(4), c: Just(5)}), Just({a: 13, b: 14, c: 15}));
eq(R.traverse(ofMaybe, R.map(R.add(10)), {a: Just(3), b: Nothing, c: Just(5)}), Nothing);
});

it('operates on a list of FL-applicatives', function() {
eq(R.traverse(Maybe, R.map(R.add(10)), [Just(3), Just(4), Just(5)]), Just([13, 14, 15]));
eq(R.traverse(Maybe, R.map(R.add(10)), [Just(3), Nothing, Just(5)]), Nothing);
Expand Down