fantasy-land icon indicating copy to clipboard operation
fantasy-land copied to clipboard

Cofoldable

Open joneshf opened this issue 11 years ago • 3 comments

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.

joneshf avatar Jan 04 '14 02:01 joneshf

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);

DrBoolean avatar May 26 '14 17:05 DrBoolean

:+1: on using Option instead of a guard func & null. Looks nice and clean to me.

SimonRichardson avatar May 27 '14 08:05 SimonRichardson

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;
};

safareli avatar Sep 18 '16 09:09 safareli