fantasy-land
fantasy-land copied to clipboard
Cofoldable
As mentioned here I'd like to propose a Cofoldable
. There's detailed information about it here
The idea is that while Foldable
and Cofoldable
are lawless alone, together you can suggest some laws on them.
It should have one of two methods:
-
fromArray :: [a] -> f a
-
unfold
I'm actually unsure on the definition of unfold
Should it be (a -> b -> b) -> b -> b -> f a
as in the definition for `build in the link, or something else? In any case, one can be derived from the other.
Please discuss.
There's an Unfoldable package that gives some guidance here:
http://hackage.haskell.org/package/unfoldable-0.8.1/docs/Data-Unfoldable.html
It even provides fromList
Regarding #7, it seems like Cofoldable makes sense over Unfoldable if the whole purpose is to provide some laws. Although in that case, my opinion is that we're being really specific about a natural transformation or isomorphism.
Anyways, for unfold:
Since this is fantasy land, I think we should use Option
to flag the end of the unfold rather than a guard fn or null.
Array's instance could be:
//+ unfold :: (b -> Option([a, b])) -> b -> [a]
Array.prototype.unfold = function(step, seed) {
var output = this;
return step(seed).cata({
Some: function(result) {
return output.concat(result[0]).unfold(step, result[1]);
},
None: function() {
return output;
}
});
}
var result = [].unfold(function(x){ return (x > 10) ? None : Some([x, x+1]); }, 0)
console.log(result);
:+1: on using Option
instead of a guard func & null.
Looks nice and clean to me.
Just an idea: chainRec
of Array could be used as unfold
Array.chainRec(function(next, done, x) {
return (x == 10) ? [done(x)] : [done(x), next(x+1)]
}, 0) // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
// implementation of Array.chainRec
function stepNext(x) { return {value: x, done: false }; }
function stepDone(x) { return {value: x, done: true }; }
Array.chainRec = function _chainRec(f, i) {
var todo = [i];
var res = [];
var buffer, xs, idx;
while (todo.length > 0) {
xs = f(stepNext, stepDone, todo.shift());
buffer = [];
for (idx = 0; idx < xs.length; idx += 1) {
(xs[idx].done ? res : buffer).push(xs[idx].value);
}
Array.prototype.unshift.apply(todo, buffer);
}
return res;
};