import Window import Debug (log) -- 旧速度vと、現在位置xから、新しい速度を求める。(はじっこだったら速度を反転する) newv : Int -> Int -> Int newv v x = if (x<= -10 || 10<=x) then -v else v -- 状態を表わす(現在位置、速度)のタプルに対して、次の状態をシグナル(fps 20)のタイミングで累積的に計算しなおすということを繰り返す。初期状態は(0,1)。結果得られるのは、(現在位置,現在の速度)を表現するシグナルである。 pos = foldp (\it (x,v) -> let nv = (newv v (log "x" x)) in (x+nv, nv) ) (0,1) (fps 20) -- 指定位置x,yを中心に●を書く(半径20の円を書いて赤で塗り潰す)。 drawCircle : Float -> Float -> Form drawCircle x y = move (x,y) <| filled red (circle 20) -- 一連の背景線を書く drawMatrix : [Form] drawMatrix = map (\x -> drawLine <| x*10) [-10..10] -- 背景線を1本書く drawLine : Float -> Form drawLine x = traced (solid blue) ( segment (x,-100) (x,100) ) -- 「一連の背景線と、●を書いたコラージュを生成する純粋関数f」に、現在位置(posタプルの第一要素)をシグナル化したまま取り出してリフト適用 main : Signal Element main=let f = \w h p-> collage w h ([drawCircle ((toFloat p)*10) 10]++drawMatrix) in f <~ Window.width ~ Window.height ~ (fst <~ pos)
解説的な何か
- foldpのpは、pastのpで、その意味は実際に「過去から現在までのシグナルの履歴値を畳み込む」です。しかし、foldp使用に伴なうオーダーは実行開始時刻から現在までの時間経過には依存せず、O(1)です。実際には、シグナルの更新1回ごとに1回呼び出される関数を登録するというものです。foldpの第一引数の関数の第二引数(上で言う(x,v))は前回のfoldpの返り値を保持しています。この値が、いわゆる状態を保持・更新するためのelmにおいての唯一の手段です。
- Debug.logは、JavaScriptでいうConsole.logを呼び出します。正格評価だからその時点の値が普通に出ます。
続く。