TypeScriptのimport指定方法

TypeScriptで作成した [State Monad](http://qiita.com/Kitam/items/b624266f89adb15278cd)をモジュールにしてみた。
importの指定に、若干迷いましたので共有します。

今回の目標
----------------
TypeScriptのモジュール化を行う。

モジュールの配置
----------------
State Monadモジュールは、ファイル名`stateMonad.ts`とし、`root/monad/state/stateMonad.ts`に配置する。
Stackモジュールは、ファイル名`stack.ts`とし、`root/stack/stack.ts`に配置する。
テストモジュールは、ファイル名`stackTest.ts`とし、`root/stackTest.ts`に配置する。

 State Monadモジュール
----------------

```ts:root/monad/state/stateMonad.ts
export
  module monad.state {
    export 
      interface Tuple2<A,B> {
        fst: A
        snd: B
      }
    export
      class State<T,X>{
        runState: (t:T) => Tuple2<X,T>
        evalState = (t:T):X => this.runState(t).fst
        execState = (t:T):T => this.runState(t).snd
        constructor(g:(t:T) => Tuple2<X,T>){
          this.runState = g
        }
        static returns<T,X>(v:X):State<T,X>{
          return new State<T,X>((t:T) => { return {fst:v, snd:t } })
        } 
        bind<B>(f: (x:X) => State<T,B>):State<T,B>{
          var g = (t:T) => {
            var st = this.runState(t)
            return f(st.fst).runState(st.snd)
          }
          return new State<T,B>(g)
        }
      }
    export
      class MonadState {
        static get<T>():State<T,T> {
          var g = (t:T) => {
            return { fst: t, snd: t }
          }
          return new State<T,T>(g)
        }
        static put<T>(a:T):State<T,void> {
          var g = (t:T) => {
            return { fst: null,  snd: a }
          }
          return new State<T,void>(g)
        }
      }
}
```

モジュールとして外部に提供する`module`、`class`には`export`を付加した。
`Tuple2`は本来なら別モジュールとするべきだが、今回はこのモジュールに含めた。
 
 Stackモジュール
----------------

```ts:root/stack/stack.ts
import ms = require("../monad/state/stateMonad")
export
  module stack {
    export 
      class Stack<X> {
        pop = <X>():ms.monad.state.State<X,X[]> =>
          ms.monad.state.MonadState.get<X[]>()
            .bind((e:X[]) => { 
                 return ms.monad.state.MonadState.put<X[]>(e.slice(1))
                             .bind(k => ms.monad.state.State.returns(e[0])) })

        push = <X>(i:X):ms.monad.state.State<X,void> =>
          ms.monad.state.MonadState.get<X[]>()
            .bind((e:X[]) => 
                 ms.monad.state.MonadState.put<X[]>([i].concat(e)))
      }
  }
```

外部モジュールの`stateMonad.ts`を使用するため、`import`が必要。
`require`はこのモジュールからの相対パスを指定する。
また、外部モジュールを使用する際は、`import`に使用した`ms.`にフォルダ名`monad.state.`を付加して使用する。
 
 テストモジュール
----------------

```ts:root/stackTest.ts
import ms = require("./monad/state/stateMonad")
import st = require("./stack/stack")

var fnc = <X>(st:st.stack.Stack):ms.monad.state.State<X,X[]> =>
  st.pop()
    .bind(e => st.pop())
    .bind(e => st.push(20))
    .bind(e => st.pop())
    .bind(e => st.push(e*5))

console.log(fnc(new st.stack.Stack<number>()).execState([1,2,3])) //=> [100,3]
```

外部モジュールの`stateMonad.ts`、`stack.ts`の`import`が必要。
ここでも相対パスを指定する。
 
 コンパイル
----------------
コンパイルする際は、`--module commonjs`のオプションを付加する。
Webで見ると`--module amd`でも良いと書いてあるが、私の環境では実行時にエラーとなった。
rootに移動し、コンパイルコマンドを発行する。

```js:/root
ts stateTest.ts --module commonjs
```

 実行
----------------
rootに移動し、node.jsにて実行する。

```js:/root
node stateTest.js // [100,3]
```

期待した値が表示された。
 
 まとめ
----------------
以前`import`に指定していた`module`がdeprecatedになっているため、`require`を使用する。
`require`には相対パスを指定する（別の方法があるかもしれません）。
外部クラスを使用する場合は、`import`に使用した変数（今回の場合は`ms`）と、フォルダ階層を`.`で区切り指定する。
コンパイル時には、`--module commonjs`のオプションを付加する。