Either monad bind

https://github.com/eu81273/jsfiddle-console

by dimitrs_papadimitriou

HTML

<script src="https://rawgit.com/eu81273/jsfiddle-console/master/console.js"></script>

JavaScript

class Maybe {
    map(f) {
      throw new Error('You have to implement the method map!');
    }
    matchWith(pattern) {
      throw new Error('You have to implement the method matchWith!');
    }

    bind(f) {
      throw new Error('You have to implement the method bind!');
    }
  }

  class Some extends Maybe {

    constructor(value) {
      super();
      this.value = value;
    }

    map(f) {
      return new Some(f(this.value))
    }

    matchWith(pattern) {
      return pattern.some(this.value)
    }

    bind(f) {
      return f(this.value)
    }
  }

  class None extends Maybe {
    map(f) {
      return new None();
    }
    matchWith(pattern) {
      return pattern.none()
    }
    bind(f) {
      return new None()
    }
  }



  class Either {
    map(f) {
      throw new Error('You have to implement the method map!');
    }
    matchWith(pattern) {
      throw new Error('You have to implement the method matchWith!');
    }
    bind(f) {
      return this.matchWith({
        left: (e) => new Left(e),
        right: (v) => f(v)
      })
    }
  }

  class Right extends Either {
    constructor(value) {
      super();
      this.value = value;
    }

    map(f) {
      return new Right(f(this.value))
    }

    matchWith(pattern) {
      return pattern.right(this.value)
    }

  }

  class Left extends Either {
    constructor(value) {
      super();
      this.value = value;
    }

    map(f) {
      return new Left(this.value);
    }
    matchWith(pattern) {
      return pattern.left(this.value)
    }

  }


  Array.prototype.matchWith = function (pattern) {
    return this.length === 0 ? pattern.empty() : pattern.concat(this.shift(), this);
  };



  Array.prototype.firstOrNone = function (predicate) {
    return this.matchWith({
      empty: () => new None(),
      concat: (value, rest) => predicate(value) ?
        new Some(value) :
        rest.firstOrNone(predicate)
    })
  }

  Maybe.prototype.ToEither = function (defaultLeft) {
    return...