Option Types with Ramda, ES6 Classes and Flow

I'm going through the FP in Scala book right now, and after going through the exceptions chapter for the Option/Either monads, figured I'd demonstrate how easy it is to do something similar in JS w/ ES6 classes, Ramda's cond for pattern matching, and flow for type checking. The following below is just a demo - there are some not great practices here (defining classes after they're used etc.) but this is more just to demonstrate how easy it is to create great/robust types w/ Flow, and how helpful R.cond can be to achieve it. If you're interested in a better implementation of this that has full flow support and a workaround to support higher kinded types, I highly recommend gcanti's Flow-Static-Land Library

// @flow
import {
  call,
  is,
  compose,
  cond,
  always,
  prop,
  construct,
  ifElse,
} from 'ramda'

class Option<A> {
  map<B>(f: A => B): Option<B> {
    return call(cond([
      [is(None), always(none)],
      [is(Some), compose(some, f, prop('value'))],
    ]), this)
  }

  getOrElse<B>(other: B): B {
    return call(cond([
      [is(None), always(other)],
      [is(Some), prop('value')],
    ]), this)
  }

  flatMap<B>(f: A => Option<B>): Option<B> {
    return this.map(f).getOrElse(none)
  }

  orElse<B>(ob: Option<B>): Option<B> {
    return this.map(some).getOrElse(ob)
  }

  filter(f: A => boolean): Option<A> {
    return this.flatMap(ifElse(f, some, always(none)))
  }

}

class Some<A> extends Option<A> {
  value: A
  constructor(x) {
    super(x)
    this.value = x
  }
  toString() {
    return `Some(${String(this.value)})`
  }
}

class None extends Option {
  static toString() {
    return 'None'
  }
}

const none = construct(None)()
const some = construct(Some)