Skip to content

Commit

Permalink
Merge pull request #534 from sanctuary-js/davidchambers/type-classes
Browse files Browse the repository at this point in the history
  • Loading branch information
davidchambers authored May 10, 2018
2 parents df5b5f0 + caed1c4 commit af9de58
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 34 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
],
"dependencies": {
"sanctuary-def": "0.16.0",
"sanctuary-type-classes": "8.1.1",
"sanctuary-type-classes": "8.2.1",
"sanctuary-type-identifiers": "2.0.1"
},
"ignore": [
Expand Down
93 changes: 63 additions & 30 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,15 @@
};
}

// C :: (a -> b -> c) -> b -> a -> c
function C(f) {
return function(y) {
return function(x) {
return f (x) (y);
};
};
}

// Fn :: Type -> Type -> Type
function Fn(x) {
return function(y) {
Expand Down Expand Up @@ -936,6 +945,40 @@
impl: map
};

//# flip :: Functor f => f (a -> b) -> a -> f b
//.
//. Curried version of [`Z.flip`][]. Maps over the given functions, applying
//. each to the given value.
//.
//. Replacing `Functor f => f` with `Function x` produces the C combinator
//. from combinatory logic:
//.
//. Functor f => f (a -> b) -> a -> f b
//. Function x (a -> b) -> a -> Function x b
//. Function x (a -> c) -> a -> Function x c
//. Function x (b -> c) -> b -> Function x c
//. Function a (b -> c) -> b -> Function a c
//. (a -> b -> c) -> b -> a -> c
//.
//. ```javascript
//. > S.flip (S.concat) ('!') ('foo')
//. 'foo!'
//.
//. > S.flip ([Math.floor, Math.ceil]) (1.5)
//. [1, 2]
//.
//. > S.flip ({floor: Math.floor, ceil: Math.ceil}) (1.5)
//. {floor: 1, ceil: 2}
//.
//. > S.flip (Cons (Math.floor) (Cons (Math.ceil) (Nil))) (1.5)
//. Cons (1) (Cons (2) (Nil))
//. ```
_.flip = {
consts: {f: [Z.Functor]},
types: [f (Fn (a) (b)), a, f (b)],
impl: curry2 (Z.flip)
};

//# bimap :: Bifunctor f => (a -> b) -> (c -> d) -> f a c -> f b d
//.
//. Curried version of [`Z.bimap`][].
Expand Down Expand Up @@ -1596,30 +1639,6 @@
impl: curry5
};

//# flip :: (a -> b -> c) -> b -> a -> c
//.
//. Takes a curried binary function and two values, and returns the
//. result of applying the function to the values in reverse order.
//.
//. This is the C combinator from combinatory logic.
//.
//. ```javascript
//. > S.flip (S.concat) ('foo') ('bar')
//. 'barfoo'
//. ```
function flip(f) {
return function(x) {
return function(y) {
return f (y) (x);
};
};
}
_.flip = {
consts: {},
types: [Fn (a) (Fn (b) (c)), b, a, c],
impl: flip
};

//. ### Composition

//# compose :: Semigroupoid s => s b c -> s a b -> s a c
Expand Down Expand Up @@ -2216,13 +2235,10 @@
//. > S.fromMaybe (0) (S.Nothing)
//. 0
//. ```
function fromMaybe(x) {
return maybe (x) (I);
}
_.fromMaybe = {
consts: {},
types: [a, $Maybe (a), a],
impl: fromMaybe
impl: C (maybe) (I)
};

//# fromMaybe_ :: (() -> a) -> Maybe a -> a
Expand All @@ -2242,7 +2258,7 @@
_.fromMaybe_ = {
consts: {},
types: [$.Thunk (a), $Maybe (a), a],
impl: flip (maybe_) (I)
impl: C (maybe_) (I)
};

//# maybeToNullable :: Maybe a -> Nullable a
Expand Down Expand Up @@ -3323,7 +3339,7 @@
//. -1
//. ```
function when(pred) {
return flip (ifElse (pred)) (I);
return C (ifElse (pred)) (I);
}
_.when = {
consts: {},
Expand Down Expand Up @@ -3834,6 +3850,21 @@
impl: find
};

//# foldMap :: (Monoid m, Foldable f) => TypeRep m -> (a -> m) -> f a -> m
//.
//. Curried version of [`Z.foldMap`][]. Deconstructs a foldable by mapping
//. every element to a monoid and concatenating the results.
//.
//. ```javascript
//. > S.foldMap (String) (f => f.name) ([Math.sin, Math.cos, Math.tan])
//. 'sincostan'
//. ```
_.foldMap = {
consts: {b: [Z.Monoid], f: [Z.Foldable]},
types: [TypeRep (b), Fn (a) (b), f (a), b],
impl: curry3 (Z.foldMap)
};

//# unfoldr :: (b -> Maybe (Array2 a b)) -> b -> Array a
//.
//. Takes a function and a seed value, and returns an array generated by
Expand Down Expand Up @@ -5227,6 +5258,8 @@
//. [`Z.extend`]: v:sanctuary-js/sanctuary-type-classes#extend
//. [`Z.extract`]: v:sanctuary-js/sanctuary-type-classes#extract
//. [`Z.filter`]: v:sanctuary-js/sanctuary-type-classes#filter
//. [`Z.flip`]: v:sanctuary-js/sanctuary-type-classes#flip
//. [`Z.foldMap`]: v:sanctuary-js/sanctuary-type-classes#foldMap
//. [`Z.gt`]: v:sanctuary-js/sanctuary-type-classes#gt
//. [`Z.gte`]: v:sanctuary-js/sanctuary-type-classes#gte
//. [`Z.id`]: v:sanctuary-js/sanctuary-type-classes#id
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"dependencies": {
"sanctuary-def": "0.16.0",
"sanctuary-type-classes": "8.1.1",
"sanctuary-type-classes": "8.2.1",
"sanctuary-type-identifiers": "2.0.1"
},
"devDependencies": {
Expand Down
12 changes: 10 additions & 2 deletions test/flip.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
'use strict';

var S = require ('..');
var S = require ('./internal/sanctuary');

var List = require ('./internal/List');
var eq = require ('./internal/eq');
var map = require ('./internal/map');


var Cons = List.Cons;
var Nil = List.Nil;


test ('flip', function() {

eq (typeof S.flip) ('function');
eq (S.flip.length) (1);
eq (String (S.flip)) ('flip :: (a -> b -> c) -> b -> a -> c');
eq (String (S.flip)) ('flip :: Functor f => f (a -> b) -> a -> f b');

eq (S.flip (S.concat) ('foo') ('bar')) ('barfoo');
eq (map (S.flip (S.concat) ('!')) (['BAM', 'POW', 'KA-POW'])) (['BAM!', 'POW!', 'KA-POW!']);
eq (S.flip ([Math.floor, Math.ceil]) (1.5)) ([1, 2]);
eq (S.flip ({floor: Math.floor, ceil: Math.ceil}) (1.5)) ({floor: 1, ceil: 2});
eq (S.flip (Cons (Math.floor) (Cons (Math.ceil) (Nil))) (1.5)) (Cons (1) (Cons (2) (Nil)));

});
20 changes: 20 additions & 0 deletions test/foldMap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

var S = require ('..');

var eq = require ('./internal/eq');


test ('foldMap', function() {

eq (typeof S.foldMap) ('function');
eq (S.foldMap.length) (1);
eq (String (S.foldMap)) ('foldMap :: (Monoid b, Foldable f) => TypeRep b -> (a -> b) -> f a -> b');

function repeat(n) { return (new Array (n + 1)).join (String (n)); }
eq (S.foldMap (String) (repeat) ([])) ('');
eq (S.foldMap (String) (repeat) ([1])) ('1');
eq (S.foldMap (String) (repeat) ([1, 2])) ('122');
eq (S.foldMap (String) (repeat) ([1, 2, 3])) ('122333');

});

0 comments on commit af9de58

Please sign in to comment.