webネタ

Webエンジニアが業務に関係することをメモしていく

TypeScriptでScalaのOptionを

書いてみた。

使い方↓

Optional(x).map(i => i + 100).getOrElse(0)
Optional(x).exists(i => i % 2 == 0)

(Optionは予約されてて使えなかったのでOptionalに)

もうほとんどScalaじゃ...!

TryとかEitherならすぐ書けそうだけどリスト周り書き出すとしんどそう...

TypeScript結構いいっぽい。coffeeも試してみたいけど型が...

class OptionT<A> {
  isEmpty: boolean
  get: () => A
  map<B>(f: (a: A) => B): OptionT<B> {
    return this.isEmpty ? new None : new Some(f(this.get()))
  }
  flatMap<B>(f: (a: A) => OptionT<B>): OptionT<B> {
    return this.isEmpty ? new None : f(this.get())
  }
  getOrElse<B extends A>(d: B): A {
    return this.isEmpty ? d : this.get()
  }
  filter(f: (a: A) => boolean): OptionT<A> {
    return (this.isEmpty || f(this.get())) ? this : new None 
  }
  exists(f: (a: A) => boolean): boolean {
    return !this.isEmpty && f(this.get())
  }
}

class Some<A> extends OptionT<A> {
  isEmpty = false
  get = () => { return this.value }
  constructor(private value: A) { super() }
}

class None extends OptionT<any> {
  isEmpty = true
  get: () => any = () => { throw ""; "" }
}

var Optional = <A>(value: A) => {
  return value ? new Some<A>(value) : new None
}

メソッド全然たりてないけど...まぁ。Noneが残念な感じになってる...

てきとうにテスト

var a = Optional(1).map(v => v + 100)
console.log(a) // Some(101)

var b = Optional(0).map(v => v + 100)
console.log(b) // None

var c = Optional(1).flatMap(v => Optional(v)).map(v => v + 1)
console.log(c) // Some(2)

var d = Optional(1).filter(i => i % 2 == 0).getOrElse(0)
console.log(d) // 0

var e = Optional(1).exists(i => i % 2 == 0)
console.log(e) // false

JavaScriptでもモナドを!