Elm本をちょっとずつ読んでいますが、なんとなく似ている気がするものたちが色々登場してきたので、頭の整理!
レコード(record)
他言語で言うところの「オブジェクト」「構造体」に近いのかな〜と思いました。
(あまりそういう捉え方は良くないのかもしれませんが)
ソースコードと実行結果
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 ++ "です。")
これは剣です。重さは5で、ダメージは10です。
型の別名(type alias)
斧も作りたい!っていうときに、同じ属性を持ったレコードをまた1から作るのがだるいので、属性をあらかじめ定義しておく。と理解した。
ソースコードと実行結果
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 ]
10 5 剣
20 10 斧
カスタム型(custom type)
これはJavaで頭が止まっている自分にはなかなか入ってこなかった。
(いや、Javaとか関係なく頭が良くないだけか!?)
武器だけじゃなく魔法も追加したい!
魔法は重さじゃなくて消費MPと詠唱時間がありまーす!
けど攻撃手段には変わりないから武器と同様に管理したいな〜っていうときを想定。
ソースコードと実行結果
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)
]
剣ダメージ:10重さ:5
斧ダメージ:20重さ:10
ティルトウェイトダメージ:30消費MP:7詠唱時間:23
組み合わせ(2019/03/08 18:00追記)
カオスになりました...
使いどころを間違えているのはなんとなくわかる。
Elm guideにある通り、custom typeは不正なデータを排除するために使うのを基本にした方が良いんだろうな。
ソースコードと実行結果
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)
]
太郎100剣ダメージ:10重さ:5
二郎200斧ダメージ:20重さ:10
三郎30メリトダメージ:30消費MP:7詠唱時間:12
@ababup1192 さんからは、custom typeにプリミティブ型引数を並べまくってると、そいつらが何を意味してんのかわかんないよとご指摘いただきました。
@miyamo_madoka さんからは、型書いて表示だけだとよくわかんない、アプリ作るとかして型を使うべしとご指摘をいただきました。
いずれもごもっとも...!
今回の記事ではここまでにしときます。
次頑張ります。