Elmの Html Msg と Html msg の違いは？

Elm初心者です。
写経していて、よく`Html Msg`と`Html msg`を書き間違えて怒られました。
私はHaskellerでもあるので`msg`が型変数なのは分かるのですが、そもそも`msg`型変数が`Msg`型以外になるケースが思いつきません。

というような疑問をTwitterに投げたら`elm-origami`の作者みやも(@miyamo_madoka)さんに優しく教えていただいて腹落ちしたので、同じことに悩む初心者仲間のためにまとめ。
誤りがあればマサカリお願いします。

# そもそもElmにおけるメッセージとは
今回の記事の肝はココ

- **メッセージとは外界のイベントを表現するもので、最終的にupdate関数に渡される値のこと**

たとえば`Browser.element`をみると

``` element.elm
element :
    { init : flags -> ( model, Cmd msg )
    , view : model -> Html msg
    , update : msg -> model -> ( model, Cmd msg )
    , subscriptions : model -> Sub msg
    }
    -> Program flags model msg
```
メッセージは`view`や`subscriptions`からElmランタイムに渡されることが見てとれます。


# メッセージとMsg型
上の`Browser.element`の例でもわかるとおり、メッセージは`msg`という型変数となっていて**`Msg`型である必要はありません**
Elmにおいて`Msg`型はElmランタイムが何か裏であれこれしてくれる特別な型ではなく、ユーザーが定義した単なるカスタム型でしかありません。
Elmランタイムからみて`Msg`型の定義は必須ではなく**`Int`や`String`がメッセージを運んでくれるなら**`Html Int`でも`Html String`でも良いわけです。
試しに https://elm-lang.org/examples/buttons を`Msg`型を使わずに書き換えてみます。

``` diff_elm
module Main exposing (..)
import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)

main =
  Browser.sandbox { init = init, update = update, view = view }

type alias Model = Int
init : Model
init =
  0

- type Msg
-   = Increment
-   | Decrement


- update : Msg    -> Model -> Model
+ update : String -> Model -> Model
update msg model =
  case msg of
-   Increment  ->
+  "Increment" ->
      model + 1
-   Decrement  ->
+  "Decrement" ->
      model - 1  
+   _  ->
+     model


- view : Model -> Html Msg
+ view : Model -> Html String
view model =
  div []
-    [ button [ onClick  Decrement  ] [ text "-" ]
+    [ button [ onClick "Decrement" ] [ text "-" ]
     , div [] [ text (String.fromInt model) ]
-    , button [ onClick  Increment  ] [ text "+" ]
+    , button [ onClick "Increment" ] [ text "+" ]
    ]
```
**メッセージとして単なる`String`を使う**ようにしただけですが、変更前と同じように動作します。
（メッセージを`String`にするとupdate関数で *「"Incriment"と"Decriment"以外のメッセージが送られる可能性あるだろ？そのための処理も書けよ」* とコンパイラに怒られて処理を追加しました。こういうところが「**Elm流石！**」と思うところ）

# 混乱の考察
`msg`という型変数名は 「ここにバインドされる型がメッセージの役割を満たす 」 という意図を明示しており可読性も向上する一方で、字面として 「この型は`Msg`になる」 とも読めてしまうため混乱します。


**「`msg`と`Msg`が似すぎているのがいけない」**、ということならば上で書いたとおり`Msg`はただのカスタム型なので、例えば先程のプログラムの型名だけを書き換えても動きます。

```diff_elm
- type Msg
+ type Message

- update : Msg     -> Model -> Model
+ update : Message -> Model -> Model

- view : Model -> Html Msg
+ view : Model -> Html Message
```
実際のアプリケーションでは、単純な`Msg`型よりずっと複雑な型をメッセージとして受け渡しする例もあるそうです。

# もう少し具体例

``` .elm
view : Html msg
view = div [] []
```
この例はイベントがない（`onClick`などがない）ため、型変数はまだ何にもバインドされていません。

```.elm
type Msg = Click

view : Html Msg
view = div [ onClick Click ] []
```
こちらは`Msg`型のイベントがあるので、型変数は`Msg`にバインドされ`Html Msg`という具体型になります。

```.elm
innerView : Html msg
innerView = div [] []

view : Html Msg
view = div [ onClick Click ] [ innerView ]
```
`innerView`の型変数`msg`は単独では1つ目の例と同じですが、`view`の中で最終的に`Msg`型にバインドされるため、うまくいきます。

# 結論

- **viewやsubscriptionsなどからElmランタイム経由でupdateにを送られるメッセージは`Msg`型である必要はなく、任意の型で良いので定義は具体型ではなく型変数が使われている**
- 一方でメッセージにはカスタム型として`Msg`を定義して使うことで網羅性の保証などの多くの利点が得られるため、そのようにすることが多い

#参考
本記事の執筆のためこちらを参照・引用させていただきました
https://discourse.elm-lang.org/t/html-msg-vs-html-msg/2758

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">この説明でわかるかわかりませんが。<br><br>Html msg型の型変数はマーカー的なものでonClickなどのイベントでランタイムに送る型を表しています<br>ランタイムからupdate関数に送られるのでupdateでうける型ともいえます<br><br>IntやStringでも問題ないです。その場合IntやStringがイベントで送られてくる感じです</p>&mdash; 3拍子が好き（みやも） (@miyamo_madoka) <a href="https://twitter.com/miyamo_madoka/status/1398153583648858116?ref_src=twsrc%5Etfw">May 28, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>