Skip to content

Commit 8efcecd

Browse files
committed
stack-safe Foldable/Traversable Array instances
Also change fold{l,r}Array to for loops because they're faster.
1 parent 2833656 commit 8efcecd

File tree

13 files changed

+209
-3
lines changed

13 files changed

+209
-3
lines changed

.jscsrc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"preset": "grunt",
3+
"disallowSpacesInAnonymousFunctionExpression": null,
4+
"requireSpacesInAnonymousFunctionExpression": {
5+
"beforeOpeningRoundBrace": true,
6+
"beforeOpeningCurlyBrace": true
7+
},
8+
"disallowSpacesInsideObjectBrackets": null,
9+
"requireSpacesInsideObjectBrackets": "all",
10+
"validateQuoteMarks": "\"",
11+
"requireCurlyBraces": null
12+
}

.jshintrc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"bitwise": true,
3+
"eqeqeq": true,
4+
"forin": true,
5+
"freeze": true,
6+
"funcscope": true,
7+
"futurehostile": true,
8+
"globalstrict": true,
9+
"latedef": true,
10+
"maxparams": 1,
11+
"noarg": true,
12+
"nocomma": true,
13+
"nonew": true,
14+
"notypeof": true,
15+
"singleGroups": true,
16+
"undef": true,
17+
"unused": true,
18+
"eqnull": true
19+
}

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"purescript-maybe": "~0.3.0"
2929
},
3030
"devDependencies": {
31-
"purescript-console": "~0.1.0"
31+
"purescript-console": "~0.1.0",
32+
"purescript-assert": "~0.1.0"
3233
}
3334
}

docs/Data.Foldable.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class Foldable f where
1111

1212
##### Instances
1313
``` purescript
14+
instance foldableArray :: Foldable Array
1415
instance foldableMaybe :: Foldable Maybe
1516
instance foldableFirst :: Foldable First
1617
instance foldableLast :: Foldable Last

docs/Data.Traversable.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class (Functor t, Foldable t) <= Traversable t where
1010

1111
##### Instances
1212
``` purescript
13+
instance traversableArray :: Traversable Array
1314
instance traversableMaybe :: Traversable Maybe
1415
instance traversableFirst :: Traversable First
1516
instance traversableLast :: Traversable Last

gulpfile.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,29 @@
33

44
var gulp = require("gulp");
55
var plumber = require("gulp-plumber");
6+
var jshint = require("gulp-jshint");
7+
var jscs = require("gulp-jscs");
68
var purescript = require("gulp-purescript");
9+
var run = require("gulp-run");
710

811
var sources = [
912
"src/**/*.purs",
1013
"bower_components/purescript-*/src/**/*.purs"
1114
];
1215

1316
var foreigns = [
17+
"src/**/*.js",
1418
"bower_components/purescript-*/src/**/*.js"
1519
];
1620

17-
gulp.task("make", function() {
21+
gulp.task("lint", function() {
22+
return gulp.src("src/**/*.js")
23+
.pipe(jshint())
24+
.pipe(jshint.reporter())
25+
.pipe(jscs());
26+
});
27+
28+
gulp.task("make", ["lint"], function() {
1829
return gulp.src(sources)
1930
.pipe(plumber())
2031
.pipe(purescript.pscMake({ ffi: foreigns }));
@@ -39,4 +50,13 @@ gulp.task("dotpsci", function () {
3950
.pipe(purescript.dotPsci());
4051
});
4152

53+
gulp.task("test", ["make"], function() {
54+
return gulp.src(sources.concat(["test/Main.purs"]))
55+
.pipe(plumber())
56+
.pipe(purescript.psc({ main: "Test.Main"
57+
, ffi: foreigns.concat(["test/Main.js"])
58+
}))
59+
.pipe(run("node"));
60+
});
61+
4262
gulp.task("default", ["make", "docs", "dotpsci"]);

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
"gulp": "^3.8.11",
55
"gulp-plumber": "^1.0.0",
66
"gulp-purescript": "^0.5.0",
7-
"gulp-run": "^1.6.7"
7+
"gulp-run": "^1.6.7",
8+
"gulp-jscs": "^1.6.0",
9+
"gulp-jshint": "^1.10.0"
810
}
911
}

src/Data/Foldable.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* global exports */
2+
"use strict";
3+
4+
// module Data.Foldable
5+
6+
exports.foldrArray = function (f) {
7+
return function (init) {
8+
return function (xs) {
9+
var acc = init;
10+
var len = xs.length;
11+
for (var i = 0; i < len; i++) {
12+
acc = f(xs[i])(acc);
13+
}
14+
return acc;
15+
};
16+
};
17+
};
18+
19+
exports.foldlArray = function (f) {
20+
return function (init) {
21+
return function (xs) {
22+
var acc = init;
23+
var len = xs.length;
24+
for (var i = 0; i < len; i++) {
25+
acc = f(acc)(xs[i]);
26+
}
27+
return acc;
28+
};
29+
};
30+
};

src/Data/Foldable.purs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ class Foldable f where
3838
foldl :: forall a b. (b -> a -> b) -> b -> f a -> b
3939
foldMap :: forall a m. (Monoid m) => (a -> m) -> f a -> m
4040

41+
instance foldableArray :: Foldable Array where
42+
foldr = foldrArray
43+
foldl = foldlArray
44+
foldMap f xs = foldr (\x acc -> f x <> acc) mempty xs
45+
46+
foreign import foldrArray :: forall a b. (a -> b -> b) -> b -> Array a -> b
47+
foreign import foldlArray :: forall a b. (b -> a -> b) -> b -> Array a -> b
48+
4149
instance foldableMaybe :: Foldable Maybe where
4250
foldr _ z Nothing = z
4351
foldr f z (Just x) = x `f` z

src/Data/Traversable.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* global exports */
2+
"use strict";
3+
4+
// module Data.Traversable
5+
6+
exports.traverseArrayImpl = function () {
7+
function Cont (fn) {
8+
this.fn = fn;
9+
}
10+
11+
function consArray(x) {
12+
return function (xs) {
13+
return [x].concat(xs);
14+
};
15+
}
16+
17+
return function (apply) {
18+
return function (map) {
19+
return function (pure) {
20+
return function (f) {
21+
/* jshint maxparams: 2 */
22+
var buildFrom = function (x, ys) {
23+
return apply(map(consArray)(f(x)))(ys);
24+
};
25+
26+
/* jshint maxparams: 3 */
27+
var go = function (acc, currentLen, xs) {
28+
if (currentLen === 0) {
29+
return acc;
30+
} else {
31+
var last = xs[currentLen - 1];
32+
return new Cont(function () {
33+
return go(buildFrom(last, acc), currentLen - 1, xs);
34+
});
35+
}
36+
};
37+
38+
return function (array) {
39+
var result = go(pure([]), array.length, array);
40+
while (result instanceof Cont) {
41+
result = result.fn();
42+
}
43+
44+
return result;
45+
};
46+
};
47+
};
48+
};
49+
};
50+
}();

0 commit comments

Comments
 (0)