LoginSignup
11
8

More than 5 years have passed since last update.

TypescriptでscalaのOptionを実装

Posted at

いちいちnullチェックをしている時にふとscalaのOption型が恋しくなることがあります。

かと言って外部ライブラリ探してきて導入するのもなぁって思い軽めに実装した時のメモ。

早速コード

    export interface Optional<A> {
        isEmpty: boolean;
        map<B>(f: (a: A) => B): Optional<B>
        bind<B>(f: (a: A) => Optional<B>): Optional<B>
        getOrElse<A>(a: A): A
        get(): A
    }
    class Just<A> implements Optional<A> {
        private value: A;
        public isEmpty: boolean = false;
        constructor(a: A) {
            this.value = a
        }
        map<B>(f: (a: A) => B): Just<B> {
            return Some(f(this.value));
        }
        bind<B>(f: (a: A) => Just<B>): Just<B> {
            return f(this.value);
        }
        getOrElse(a: A): A{
            return this.value;
        }
        get(): A{
            return this.value;
        }
    }
    class Nothing<A> implements Optional<A> {
        private value: A;
        public isEmpty: boolean = true;
        constructor(a: A) {
            this.value = a;
        }
        map<B>(f: (a: A) => B): Nothing<B> {
            return None;
        }
        bind<B>(f: (a: A) => Just<B>): Nothing<B> {
            return None;
        }
        getOrElse<A>(a: A): A{
            return a;
        }
        get(): A {
            throw Error("NoSuchElementException");
        }
    }
    export const None = new Nothing(null);

    export function Some<A>(a: A): Just<A>{
        return new Just(a);
    }

使用例

Some(10).map(a => a * 10).get()
=> 100

Option型ってmonad だよね?

モナド則とは以下
1. (return x) >>= f == f x
2. m >>= return == m
3. (m >>= f) >>= g == m >>= (\x -> f x >>= g)

検証してみる

以下の様な関数fを定義しときます。

var f = a => {return new Just("FFF!!!")};

1. (return x) >>= f == f x

(Some("Monad!").bind(f).get() === f("Monad!").get()

2. m >>= return == m

new Just("Monad!").bind(Some).get() === Some("Monad!").get()

3. (m >>= f) >>= g == m >>= (\x -> f x >>= g)

関数gの定義

var g = (x) => new Just("GGG!")
var left = (new Just("Monad!").bind(f)).bind(g).get()
var right = new Just("Monad!").bind(x => {return f(x).bind(g)}).get()
left === right

まとめ

コードは短いですがライブラリ入れたほうが楽かもですね・・・

11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8