sanctuary-js / sanctuary

:see_no_evil: Refuge from unsafe JavaScript
https://sanctuary.js.org
MIT License
3.03k stars 94 forks source link

Update head and tail to work for all Foldable #570

Closed Bradcomp closed 5 years ago

Bradcomp commented 6 years ago

Currently Head and Tail only work for Array, but it is possible to implement them for all Foldable.

Bradcomp commented 6 years ago

Sample head implementation:

const f = S.reduce(b => a => S.maybe(S.Just(a))(_ => b)(b))(S.Nothing)

Sample, but incomplete tail implementation:

const tail = xs => {
  let skipped = false;
  return Z.reduce ((xs, x) => {
    if (skipped) {
      return Z.append (x, xs);
    } else {
      skipped = true;
      return xs;
    }
  }, [], xs);
};
masaeedu commented 6 years ago

Here's a complete tail implementation:

// tail :: (Foldable f, Applicative g, Monoid g) => TypeRep g -> f a -> Maybe (g a)
const tail = tr =>
  S.reduce
    (b => a =>
      S.maybe
        (S.Just(Z.empty(tr)))
        (x => S.Just(Z.concat(x, Z.of(tr, a))))
        (b))
    (S.Nothing);

[tail(Array)([]), tail(Array)([1]), tail(Array)([1, 2]), tail(Array)([1, 2, 3])]
// => [Nothing, Just ([]), Just ([2]), Just ([2, 3])]
davidchambers commented 5 years ago

@Bradcomp and @masaeedu, would one of you like to add these functions to sanctuary-type-classes?

davidchambers commented 5 years ago

@syves has expressed interest in working on these generalizations. While we're at it, let's generalize S.last and S.init. These are the desired signatures (constraints omitted with pedagogy in mind):

S.head :: ??? => f a -> Maybe a
S.last :: ??? => f a -> Maybe a
S.tail :: ??? => f a -> Maybe (f a)
S.init :: ??? => f a -> Maybe (f a)