<commit_before>import Type from 'union-type';


// `tail` function must be return a Stream type, but no way to enforce that without evaluating it :-(
const Stream = Type({
  Empty: [],
  Cons:  [() => true, Function]
});

Stream.prototype = Object.freeze({
  chain: function(f) {
    return Stream.case({
      Empty: () => Stream.Empty,
      Cons:  (head, tail) => f(head).concat(tail().chain(f))
    }, this);
  },

  concat: function(s) {
    return Stream.case({
      Empty: () => s,
      Cons:  (head, tail) => Stream.Cons(head, () => tail().concat(s))
    }, this);
  },

  head: function() {
    return Stream.case({
      Empty: () => Stream.Empty,
      Cons:  (head, _) => head
    }, this);
  },

  isEmpty: function() {
    return Stream.case({
      Empty: () => true,
      Cons:  () => false
    }, this);
  },

  isStream: () => true,

  map: function(f) {
    return Stream.case({
      Empty: () => Stream.Empty,
      Cons:  (head, tail) => Stream.Cons(f(head), () => tail().map(f))
    }, this);
  },

  of: x => Stream.Cons(x, () => Stream.Empty),

  tail: function() {
    return Stream.case({
      Empty: () => Stream.Empty,
      Cons:  (_, tail) => tail()
    }, this);
  },

  toArray: function() {
    return Stream.case({
      Empty: () => [],
      Cons:  (head, tail) => [head].concat(tail().toArray())
    }, this);
  }
});

Stream.empty = () => Stream.Empty;

Stream.isStream = s => s && s.isStream === Stream.prototype.isStream && s.isStream();

export default Stream;<commit_msg>uniion types are beautiful<commit_after>import Type from 'union-type';


// `tail` function must be return a Stream type, but no way to enforce that without evaluating it :-(
const Stream = Type({
  Empty: [],
  Cons:  [() => true, Function]
});

Stream.prototype = Object.freeze({
  chain: function(f) {
    return Stream.case({
      Empty: ()           => Stream.Empty,
      Cons:  (head, tail) => f(head).concat(tail().chain(f))
    }, this);
  },

  concat: function(s) {
    return Stream.case({
      Empty: ()           => s,
      Cons:  (head, tail) => Stream.Cons(head, () => tail().concat(s))
    }, this);
  },

  head: function() {
    return Stream.case({
      Empty: ()        => Stream.Empty,
      Cons:  (head, _) => head
    }, this);
  },

  isEmpty: function() {
    return Stream.case({
      Empty: () => true,
      Cons:  () => false
    }, this);
  },

  isStream: () => true,

  map: function(f) {
    return Stream.case({
      Empty: ()           => Stream.Empty,
      Cons:  (head, tail) => Stream.Cons(f(head), () => tail().map(f))
    }, this);
  },

  tail: function() {
    return Stream.case({
      Empty: ()        => Stream.Empty,
      Cons:  (_, tail) => tail()
    }, this);
  },

  toArray: function() {
    return Stream.case({
      Empty: ()           => [],
      Cons:  (head, tail) => [head].concat(tail().toArray())
    }, this);
  },

  toString: function() {
    return Stream.case({
      Empty: () => 'Empty',
      Cons: (head, tail) => `Cons(${head}, ${tail().toString()})`
    }, this);
  }
});

Stream.empty = () => Stream.Empty;

Stream.fromArray = xs => xs.reduceRight((acc, x) => Stream.Cons(x, () => acc), Stream.Empty);

Stream.isStream = s => s && s.isStream === Stream.prototype.isStream && s.isStream();

Stream.of = x => Stream.Cons(x, () => Stream.Empty);

export default Stream;
{'fraction_non_alphanumeric': 0.207541567695962, 'fraction_numerical': 0.0, 'mean_word_length': 2.480371900826446, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2169429', 'n_tokens_mistral': 1151, 'n_tokens_neox': 1106, 'n_words': 263}