Elmのデータ型　頭の整理

Elm本をちょっとずつ読んでいますが、なんとなく似ている気がするものたちが色々登場してきたので、頭の整理！

# レコード（record）

他言語で言うところの「オブジェクト」「構造体」に近いのかな〜と思いました。
（あまりそういう捉え方は良くないのかもしれませんが）

<details><summary>ソースコードと実行結果</summary><div>

```elm:
module Main exposing (main, sword)

import Html exposing (..)


sword =
    { damage = 10, weight = 5, name = "剣" }


main =
    text ("これは" ++ sword.name ++ "です。重さは" ++ String.fromInt sword.weight ++ "で、ダメージは" ++ String.fromInt sword.damage ++ "です。")
```

```html:実行結果（ブラウザで表示）
これは剣です。重さは5で、ダメージは10です。
```

</div></details>

# 型の別名（type alias）

斧も作りたい！っていうときに、同じ属性を持ったレコードをまた1から作るのがだるいので、属性をあらかじめ定義しておく。と理解した。

<details><summary>ソースコードと実行結果</summary><div>

```elm:
module Main exposing (main, sword)

import Html exposing (..)


type alias Weapon =
    { damage : Int
    , weight : Int
    , name : String
    }


sword =
    Weapon 10 5 "剣"


axe =
    Weapon 20 10 "斧"


swordText =
    String.fromInt sword.damage ++ " " ++ String.fromInt sword.weight ++ " " ++ sword.name


axeText =
    String.fromInt axe.damage ++ " " ++ String.fromInt axe.weight ++ " " ++ axe.name


main =
    div [] [ text swordText, br [] [], text axeText ]
```

```html:実行結果（ブラウザで表示）
10 5 剣
20 10 斧
```

</div></details>

# カスタム型（custom type）

これはJavaで頭が止まっている自分にはなかなか入ってこなかった。
（いや、Javaとか関係なく頭が良くないだけか！？）

武器だけじゃなく魔法も追加したい！
魔法は重さじゃなくて消費MPと詠唱時間がありまーす！
けど攻撃手段には変わりないから武器と同様に管理したいな〜っていうときを想定。

<details><summary>ソースコードと実行結果</summary><div>

```elm:
module Main exposing (Attack(..), axe, hit, magic, main, sword)

import Html exposing (..)


type Attack
    = Sword Int Int String
    | Axe Int Int String
    | Magic Int Int Int String


hit : Attack -> String
hit atk =
    case atk of
        Sword damage weight name ->
            name ++ "ダメージ：" ++ String.fromInt damage ++ "重さ：" ++ String.fromInt weight

        Axe damage weight name ->
            name ++ "ダメージ：" ++ String.fromInt damage ++ "重さ：" ++ String.fromInt weight

        Magic damage cost time name ->
            name ++ "ダメージ：" ++ String.fromInt damage ++ "消費MP：" ++ String.fromInt cost ++ "詠唱時間：" ++ String.fromInt time


sword =
    Sword 10 5 "剣"


axe =
    Axe 20 10 "斧"


magic =
    Magic 30 7 23 "ティルトウェイト"


main =
    div []
        [ text (hit sword)
        , br [] []
        , text (hit axe)
        , br [] []
        , text (hit magic)
        ]
```

```html:実行結果（ブラウザで表示）
剣ダメージ：10重さ：5
斧ダメージ：20重さ：10
ティルトウェイトダメージ：30消費MP：7詠唱時間：23
```

</div></details>

# 組み合わせ(2019/03/08 18:00追記)

カオスになりました...
使いどころを間違えているのはなんとなくわかる。
Elm guideにある通り、custom typeは不正なデータを排除するために使うのを基本にした方が良いんだろうな。

<details><summary>ソースコードと実行結果</summary><div>

```elm:
module Main exposing (Attack(..), Hero, Weapon, hit, main, man1, man2, man3)

import Html exposing (..)


type alias Weapon =
    { damage : Int
    , weight : Int
    , name : String
    }


type Attack
    = Sword Weapon
    | Axe Weapon
    | Magic { damage : Int, cost : Int, time : Int, name : String }


type alias Hero =
    { attackMethod : Attack
    , name : String
    , hp : Int
    }


man1 =
    Hero (Sword (Weapon 10 5 "剣")) "太郎" 100


man2 =
    Hero (Axe (Weapon 20 10 "斧")) "二郎" 200


man3 =
    Hero (Magic { damage = 30, cost = 7, time = 12, name = "メリト" }) "三郎" 30


hit : Hero -> String
hit hero =
    hero.name
        ++ String.fromInt hero.hp
        ++ (case hero.attackMethod of
                Sword weapon ->
                    weapon.name ++ "ダメージ：" ++ String.fromInt weapon.damage ++ "重さ：" ++ String.fromInt weapon.weight

                Axe weapon ->
                    weapon.name ++ "ダメージ：" ++ String.fromInt weapon.damage ++ "重さ：" ++ String.fromInt weapon.weight

                Magic attr ->
                    attr.name ++ "ダメージ：" ++ String.fromInt attr.damage ++ "消費MP：" ++ String.fromInt attr.cost ++ "詠唱時間：" ++ String.fromInt attr.time
           )


main =
    div []
        [ text (hit man1)
        , br [] []
        , text (hit man2)
        , br [] []
        , text (hit man3)
        ]
```

```html:実行結果(ブラウザで確認)
太郎100剣ダメージ：10重さ：5
二郎200斧ダメージ：20重さ：10
三郎30メリトダメージ：30消費MP：7詠唱時間：12
```

</div></details>

@ababup1192 さんからは、custom typeにプリミティブ型引数を並べまくってると、そいつらが何を意味してんのかわかんないよとご指摘いただきました。

@miyamo_madoka さんからは、型書いて表示だけだとよくわかんない、アプリ作るとかして型を使うべしとご指摘をいただきました。

いずれもごもっとも...！
今回の記事ではここまでにしときます。
次頑張ります。