Elmの型で読むReduxやVuexのアーキテクチャ

# はじめに

近年徐々に複雑になるwebフロントエンドの状態管理の仕組みとして、ReactやVue.jsといったwebフロントエンドフレームワークのお供にReduxやVuexと言ったライブラリを組み合わせて使うことが多いと思います。

それら二つのライブラリは、`Elm`という高品質webフロントエンド構築のための関数型AltJSが用いている`The Elm Architecture`と呼ばれるアーキテクチャに影響を受けて作られました。


追記:
ReduxとElmの時系列はReduxの方が先であり、しかしながら状態のimmutableなどは影響を受けていることから、
**現在の形のReduxはElmに影響を受けている所がある。**
という表現が正しかったようです。
コメントありがとうございます。

*参考
[Vuexとは何か？｜Vuex](https://vuex.vuejs.org/ja/)
[reduxjs / redux](https://github.com/reduxjs/redux)*

`Elm`の型システムや見た目は非常にリーダブルであり、型を読むだけでアーキテクチャの本質に近づけると思いますので、Elmユーザーだけでなく、Redux、Vuexがよくわからないと困っているユーザーの方でも読んでいただけたらと。

## リーディング準備

Elmの型システムや見た目が非常にリーダブルと言われたところで、いきなり読み始めて分かるわけがないので馴染みが深いTypeScriptへ変換してElmの型を読む準備をしましょう。

この記事では関数の型を使うことによりアーキテクチャの説明をしますので、関数の型のみ見ていこう！

```ts:TypeScript
function increment(x: number): number {
    return x + 1;
}
```

```elm:Elm
increment : number -> number
increment x = x + 1
```

上の二つは全く同じ関数を定義していることになります
number型を引数にとってnumber型を返すincrement関数の定義は `number -> number` と書くことができる！

引数を二つ以上取る関数の型はこの様に書きます！

```ts:TypeScript
function add(x: number, y: number): number {
    return x + y;
}
```

```elm:Elm
add : number -> number -> number
add x y = x + y
```

なぜ`(number, number) -> number`と書かないのかという疑問が湧くと思いますが、それは物凄い便利な機能と概念がバックに存在します。しかし本題からは外れますので、`部分適用`, `カリー化`という検索キーワードだけ置いておきます。

簡潔で読みやすい！準備完了！！

そしてこの記事で`関数`という言葉は同じ引数が入ってきたときに必ず引数以外の影響を受けずに同じ値を返す、数学的な純粋な関数を指します。

# 本題

## フロントエンドは関数だ

まさにブラウザに映っているビューの状態はただの関数の戻り値でしかないというのが`The Elm Architecture`の考え方であり、実装でもあります。

```elm:view関数の型
view : model -> html
```

`model` には実際には任意の型の任意の値が入っており、何かしらの値を引数にとるviewという巨大な関数が任意の`html`を返すことによってフロントエンドが構築されます。

そして、modelの値が同じであれば常に同じ`html`を構築する関数こそがviewという関数になります。

## The Elm Architectureの骨子

どんな`Elm`プログラムも次の三つの要素に分解することができます。

- Model — アプリケーションの状態
- Update — 状態を更新する方法
- View — HTMLとして状態を閲覧する方法

*引用 - https://guide.elm-lang.jp/architecture/*

既に登場したViewとModelによって実際にhtmlが構築されているのがわかりました。

しかしユーザーの操作に対して見た目が変わらないwebサイトなんて誰が作りたいでしょうか？

そこで、見た目の為の引数であるmodelの値を変更することにより、表示を変更することができます。

```elm:update関数の型
update : message -> model -> model
```

htmlから発射されたmessageとmodelを引数にして、新たな状態のmodelを返す関数となっています。

### 全体図

<img width="400px" alt="elm-architecture" src="https://programming-elm.com/img/elm-architecture.png">


*引用 [Programming Elm](https://programming-elm.com/)*

この仕組みにより、モデルを引数にとってHTMLを構築するただの関数がいろいろな状態変化をすることができる様になりました！

## 実際の型

ここまで若干抽象的な話をしてきましたが、Elmで具体的な一番最小限のアプリケーション定義である`sandbox`の実際の型を見てみましょう。

```elm:sandbox
sandbox :
    { init : model
    , view : model -> Html msg
    , update : msg -> model -> model
    }
    -> Program () model msg
```

`init`はブラウザで一番最初に表示した時の初期状態のmodelを定義します。
`view`はmodelを引数にとって、Htmlを返す関数です。おまけ付きの様な`msg`はユーザーが弄ったときにmsg型の何かしらをupdateに対して投げるよという意味です。
`update`はmsgと現在のmodelの状態を引数にして、新たなmodelを生成して返す関数です。

これらを構造体のフィールドとして定義するとプログラムになるよ！という定義です。

本当にたったこれらのシンプルな3つのことを定義するだけで、全てのことが実現できてしまうアプリケーションが完成してしまうのが`The Elm Architecture`であり、ReduxやVuexがやりたいことの本質なんですね。

# まとめ

ReduxやVuexは非常に難しい名前の関数や使い道がよくわからない関数をたくさん定義して、何をしたいのかわからなくなることがありますが、結局やりたいことはmodelを引数にしてhtmlを返す巨大な純粋関数としてwebフロントエンドを定義してあげたいだけなんですね。

```elm:結局やりたいこと
view : model -> html
```

ちなみに、Elmという言語は非常に言語仕様が堅牢でコンパクトであり、不必要な機能を全て廃した非常に学びやすい言語です。
The Elm Architectureも非常にコンパクトで堅牢な為、非常に簡単に高品質なwebフロントエンドを構築することが可能になっていますので、ぜひ皆さんも型を読むだけじゃなくて試してみてくださいね。