- Elm Advent Calendar 2016 - Adventar 8日目
- Elmの勉強の記録
- Richard Feldman, Elm in Action MEAP V03を読みながらの感想
結果をランダムに返す処理をElmで書く
- ボタン押したらサイコロを振る、とか
- jsなら
Math.random()
だけ済んでるところで、違いを実感できる側面
- jsなら
- 型定義はどのように書くのか
- Elmの関数は純粋関数
- 同じ引数渡せば戻り値は毎回同じ
- 「呼び出すたびに戻り値が毎回違う」関数は言語設計上禁止されてる
- であれば、どうやって「サイコロ」を実装できるのか?
ElmのRandomモジュール
「ランダムな○○」をElmで実現させるために必ず使うもの。コアモジュールの1つ
- 乱数生成器を作るために使う関数がRandomモジュールにまとめられてる
- 乱数生成器は、
generator
と呼ばれてるらしい
- 乱数生成器は、
- ランダムに生成させる値としては、数値、文字列、Record、とか色々
- ドキュメントに少し玄人向けのNoteがついてる
- HaskellのSystem.Randomの移植
ランダムな結果をthe Elm Architectureで使えるようにするための流れ
今ひとつな説明だがこんな感じ
-
関数の式の評価はElmランタイムだが、
Cmd a
型が戻り値である関数式の評価をするときはElmランタイム側で何をしてるのかが、不明 -
コマンド(
Cmd a
型データ)を返す関数を作るor用意する- 評価されると
Cmd a
型データを取り出せる関数式 - ランダムな結果を生成する方法を記述したもの、という位置付け
- 評価されると
-
式の評価は通常通りElmランタイムの仕事
-
式の評価の結果、
Cmd a
型データを取り出した時、generatorがランライム上で実行される -
実行結果をメッセージにラップして、update関数へフィードバックする
- このフィードバックされたメッセージ中に実行結果(1〜3のうちの1つの数字、とか)がラップされてる
Cmd a
型データを使うときに頭使うとこ、難しいなと感じるとこ
-
Cmd a
型を返す関数がどれかを把握すること -
Cmd a
型を返す関数が求める引数にはややこしいものが多い
generate : (a -> msg) -> Generator a -> Cmd msg
- この
Random.generate
だけが、Random
モジュールの中では、Cmd a
型を返す - 2つの引数をとる
- 1つは、受け取った引数を
msg
型に返し、このmsg
型のデータは、戻り値にラップされる - 2つめは、
Generator a
型という、Random
モジュールで定義されたデータ型
- 1つは、受け取った引数を
-
Generator a
の型変数a
が、生成されるデータの型を指定する- 「1から3までの数字のどれか」、であれば、
Generator Int
型と指定する
- 「1から3までの数字のどれか」、であれば、
- そして
Generator a
型のデータはどうやって作るかというと、Generator a
を戻り値とする関数がRandom
モジュールには複数存在する- ランダムに
Int
生成させたいなら、Random.init
-
Random.init 1 3
と範囲を指定
-
-
True
,False
なら、Random.bool
-
String
やRecord
とかリストになると、Generator a
を加工する関数を使う- union typeとRandom.initとか組み合わせるやつとか
- ランダムに
実装例を読む
例はElm in Actionから、
randomPhotoPicker : Random.Generator Int
randomPhotoPicker =
Random.int 0 (Array.length photoArray - 1)
type Msg
| SelectByIndex Int
| SurpriseMe
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SelectByIndex index ->
( { model | selectedUrl = getPhotoUrl index }, Cmd.none )
SurpriseMe ->
( model, Random.generate SelectByIndex randomPhotoPicker )
- update関数
-
( Model, Cmd Msg )
返す
-
- update関数の
case...of
のSurpriseMe
ブランチで、Cmd Msg
型データを返してる -
Msg
型はunion typesとして定義 -
Random.generate SelectByIndex randomPhotoPicker
がメイン部分-
randomPhotoPicker
は、Generator Int
型 -
SelectByIndex
は、Msg
型定義を変形した、Int -> Msg
型
-
- update関数はtype constructor
SurpriseMe
というMsg型のデータを受け取ると、Cmd (SelectByIndex Int)
をElmランタイムに投げる。 - type constructor
SelectByIndex Int
のメッセージをElmランタイムからupdate関数は受け取る
参考ページ
- Randomモジュールの説明
-
An Introduction to Elm のRandom
- 最新版のdocでは削除されてる