Download presentation
Presentation is loading. Please wait.
Published byEdwina Boone Modified over 9 years ago
1
Elm Signals and Suggestions
2
Working online In general, I found working online at http://elm-lang.org/try to be the best way to program Elmhttp://elm-lang.org/try Instant feedback, so you can try one change at a time and see if it worked No good way to save your work; I did an occasional copy-all and paste into Sublime Text The images used in the examples are on the server, not locally, so you can’t readily use them in your own program I installed Elm and used the elm repl to test single expressions and very small bits of code The REPL is especially useful for entering expressions to find out their type > Signal.map : (a -> b) -> Signal.Signal a -> Signal.Signal b 2
3
Program structure Elm programs have a structure very similar to MVC (Model-View-Controller) The structure is Model - Update - View, or sometimes Model - Update - View - Signals In Elm The Model is typically just data, describing the current state of the program; typically this is in the form of a record named model The Update is a set of pure functions; typically there is a function named update with a signature similar to Input -> Model -> Model The View is a set of functions whose purpose is to display the current state; typically there is a function named view with a signature something like Input -> Model -> Element The Signals part includes a function named main ; it collects signals together and bundles them up, sends them to update to get a new program state, and sends the result to view 3
4
Mouse signals import Mouse exposing (..) position : Signal ( Int, Int ) x : Signal Int y : Signal Int isDown : Signal Bool clicks : Signal () 4
5
Keyboard signals import Keyboard exposing (..) Mouse.position : Signal (Int, Int) arrows : Signal { x : Int, y : Int } wasd : Signal { x : Int, y : Int } enter, space, ctrl, shift, alt, meta are all Signal Bool type alias KeyCode = Int isDown : KeyCode -> Signal Bool keysDown : Signal (Set KeyCode) presses : Signal KeyCode -- most recent key pressed 5
6
Time signals import Time exposing (..) fps : number -> Signal Time fps (frames per second) will produce a signal the given number of times every second fpsWhen : number -> Signal Bool -> Signal Time Same as the fps function, but you can turn it on and off every : Time -> Signal Time Takes a time interval t and produces a signal updated every t delay : Time -> Signal a -> Signal a Delays a time signal There a few additional functions 6
7
Window signals import Window exposing (..) dimensions : Signal ( Int, Int ) width : Signal Int height : Signal Int When you embed Elm in a it gives the dimensions of the container, not the whole window 7
8
Monads Signal is a monad type Signals, by definition, vary over time Clearly, this is inappropriate for a pure functional language Monads “isolate” impure operations The main function in the Signals part of an Elm program: 1. Collects signals together and bundles them up 2.Extracts the data from the signals and sends them to the pure function update to get a new program state 3.Sends the new program state to view 8
9
Bind Remember “bind” ( >>= ) in Haskell? bind takes a value out of a monad, applies a function to it, and puts the result back into a monad: (>>=) :: Monad m => m a -> (a -> m b) -> m b Elm has something similar but not identical Signal.map : (a -> b) -> Signal a -> Signal b This allows us to take a Signal a, use it to call a pure function (a -> b), and get the result as a Signal b The arguments are reversed from those of >>= but in the same order as those of List.map List.map : (a -> b) -> List a -> List b <~ is an alias for Signal.map 9
10
Signal.map n Signal.map applies a pure function to the value inside a Signal, producing another Signal Signal.map : (a -> b) -> Signal a -> Signal b However, you often have pure functions that take more than a single argument map2 : (a -> b -> result) -> Signal a -> Signal b -> Signal result The result type is, of course, up to the supplied function, but is often a tuple map3 : (a -> b -> c -> result) -> Signal a -> Signal b -> Signal c -> Signal result map4 : (a -> b -> c -> d -> result) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal result map5 -- the obvious type is omitted for reasons of space 10
11
Warning! lift Elm is a new and rapidly changing language If you find examples using the functions lift, lift2, lift3, etc., these functions no longer exist They have been replaced by map, map2, map3, etc. The old functions have the same signature as the new, and as far as I know, is just a name change 11
12
Sampling import Signal exposing (..) sampleOn : Signal a -> Signal b -> Signal b Sample from the second input every time an event occurs on the first input. For example, (sampleOn clicks (every second)) will give the approximate time of the latest click The value of the first signal ( Signal a ) is discarded I believe that the purpose of sampleOn is to restrict the number of events that must be handled by the update and view parts of the program Mouse.position can probably produce hundreds of events a second 12
13
foldp foldp folds signals “over time” From the documentation: foldp : (a -> state -> state) -> state -> Signal a -> Signal state Create a past-dependent signal. Each update from the incoming signals will be used to step the state forward. The outgoing signal represents the current state. 13
14
Mario example I main : Signal Element main = Signal.map2 view Window.dimensions (Signal.foldp update mario input) view : (Int, Int) -> Model -> Element update : (Float, Keys) -> Model -> Model 14
15
Mario example II main : Signal Element main = Signal.map2 view Window.dimensions (Signal.foldp update mario input) input : Signal (Float, Keys) input = let delta = Signal.map (\t -> t/20) (fps 30) in Signal.sampleOn delta (Signal.map2 (,) delta Keyboard.arrows) 15
16
Modified Mario I I modified the Mario example to also accept mouse position signals main : Signal Element main = Signal.map3 view Window.dimension Mouse.position (Signal.foldp update mario input) view : (Int, Int) -> (Int, Int) -> Model -> Element update : (Float, Keys) -> Model -> Model 16
17
Modified Mario II main : Signal Element main = Signal.map3 view Window.dimension Mouse.position (Signal.foldp update mario input) input : Signal (Float, Keys, Location) input = let delta = Signal.map (\t -> t/20) (fps 30) in Signal.sampleOn delta (Signal.map3 (,,) delta Keyboard.arrows Mouse.position) 17
18
Modified Mario III type alias Model = { x : Float, y : Float, vx : Float, vy : Float, dir : Direction, mouse : (Int, Int) } update : (Float, Keys, Location) -> Model -> Model update (dt, keys, position) mario = mario |> gravity dt |> jump keys |> walk keys |> physics dt |> attract position -- defined as type alias Location = (Int, Int) 18
19
Questions main : Signal Element main = Signal.map3 view Window.dimension Mouse.position (Signal.foldp update mario input) input : Signal (Float, Keys, Location) input = let delta = Signal.map (\t -> t/20) (fps 30) in Signal.sampleOn delta (Signal.map3 (,,) delta Keyboard.arrows Mouse.position) Why isn’t Window.dimension handled in input ? Why do I need to mention Mouse.position twice? 19
20
Collage example A Collage is used to display things on the screen view : (Int, Int) -> (Int, Int) -> Model -> Element view (w',h') mario = let -- many definitions omitted: w, h, marioImage, etc. in collage w' h' [ rect w h |> filled (rgb 174 238 238), rect w 50 |> filled (rgb 74 167 43) |> move (0, 24 - h/2), marioImage |> toForm |> move position ] 20
21
21 The End
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.