# Map to the Future

Where we make random stuff with a `Generator`, and work in the future

me> So… what if I wanted to get a random value…

wat> Just input the time coordinates and accelerate to 88 miles per hour…

me> I want to get a random *value* not a random *answer* 😠

wat> It kinda wasn’t. Thing is, Elm can’t give you a random value.

me> But… you told me a `Generator a` was something that could give me a random `a` 😢

wat> Wait, don’t cry. It can five you a pseudo-random value. Which is usually random enough for most things that don’t have “crypto” in the title.

me> So, is there a function like JavaScript’s `Math.random()`?

wat> What does that `Math.random()` of yours do?

me> It gives me a random number each time I call it. Like…

`> Math.random()0.09275992481931072`

wat> Oh, so it’s a function that returns `0.09275992481931072` every time it’s called?

me> Yes… 😄 I mean, no!!! 😅 Next time we call it, it’s going to be *another* random number. Like…

`> Math.random()0.16654248115205728`
`> Math.random()0.035388785049037974`

wat> 🤔 So, let me get this straight: this is a function which, given the same (absence of) parameters, returns a different value each time? 😐

me> Pretty much.

wat> Oh 😶 Then no, we can’t do that in Elm. Elm’s functions are pure. No silly side-effect. Given the same parameters, they always return the same results.

me> But you said…

wat> That you could get pseudo-random stuff, yes. That’s (part of) why the *pseudo* is here actually. What it means is that, in order to get different results every time, you need to give the (pseudo-)random generation function a parameter (called a “seed”) that has to be different every time.

me> So, every time I call the function with the same seed, I get the same result, but when I call it with a different seed every time, I get different results? Well, that’s all well and fine but since I don’t know how to get a new random seed each time that does not solve my problem now, does it? 😠

wat> 😅 now let’s not get too worked up, I have good news! Let’s say I wrote a pseudo-random generation function that generates an `Int` using a `Seed` (that is conveniently also an int) ; I could also make it return a new `Seed` that can be used for the next generation. Look:

`gimmePseudoRandom : Seed -> (Seed, Int)gimmePseudoRandom seed =    -- the code of this algorithm is not the subject here :)    -- just note that the result type (Seed, Int) is a tuple    -- that contains the new Seed first, and second the Int    -- we wanted generated`
`> gimmePseudoRandom 12345679(791811582, 3)-- 3 is your random result, 791811582 is the next seed`
`> gimmePseudoRandom 12345679(791811582, 3)-- given the same seed (12345679), it gives you the exact same-- pseudo-random number (3), and the exact same seed (791811582)`
`> gimmePseudoRandom 791811582(9377838711, 127)-- now using the next seed we obtained earlier, it gives you another -- pseudo-random number (127), and another next seed (9377838711)`

me> Hmm… sooo… ok, it’s not random, but it’s close enough… still, I have to give it a seed, and remember the next seed for next time I want to generate a pseudo-random number… sounds complicated. 😒

wat> Sure ; that’s probably what your JavaScript does behind your back though, I’d wager that your `Math.random()` function has a hidden side-effect that remembers the next seed generated every time and works with it to give you the next number…

me> Why can’t Elm be more simple, like JavaScript… 😞

wat> Don’t lament… 😃 because it kinda is!

me> But you just said?…

wat> The good people that made Elm had an idea to put that seed-y business somewhere it shouldn’t bother you too much. Like (almost) all side-effects in Elm, they are contained in the bowels of the Elm architecture, to which you can send commands (sending a `Cmd msg`) and receive messages from (`update : msg -> model -> (model, Cmd msg)`) so you can modify your state (and possibly send other commands).

me> So… you mean that I’ll somehow use `Cmd msg` to tell the architecture to give me pseudo-random stuff? :

wat> Exactly! Now, let’s see how it really works with an example ; say I have something like this:

`import Random exposing (Generator)`
`-- this is a simple representation of a 6-faced dietype Die = One | Two | Three | Four | Five | Six`
`-- this is also our modeltype alias Model = Die`
`-- there are two messages that affect our modeltype Msg    = Throw      -- one is sent when the user wants to throw the die    | NewValue Die      -- one that gives us the new face of the die`
`-- this is our generator for a new die valuedieGenerator : Generator DiedieGenerator =    Random.int 1 6        |> Random.map (\intValue ->            case intValue of                1 -> One                2 -> Two                3 -> Three                4 -> Four                5 -> Five                6 -> Six                _ -> One        )    -- don't worry if it looks barbaric now, we'll explain soon :)`
`update : Msg -> Model -> (Model, Cmd Msg)update msg model =    case msg of        Throw ->            ( model              -- the model stays as is since we don't have              -- a new value yet            , Random.generate NewValue dieGenerator              -- to get the new value, we send a command that will              -- return to us with the NewValue message containing              -- the new value            )`
`        NewValue value ->            ( value              -- this time we actually change the value of the die            , Cmd.none              -- and we don't have any new command to send            )`

me> So… you have made a `dieGenerator` to make random `Die` values… and you feed it to `Random.generate` along with `NewValue`… why? 😳

wat> Look at the signature for `Random.generate`:

`Random.generate : (value -> msg) -> Generator value-> Cmd msg`

me> Ah, I see! 😃 You give a function that will make a `msg` using the `value` generated, a `Generator` that will generate that `value`, and you get a nicely wrapped `Cmd` that will return with the very `msg` wrapping the `value` as soon as it’s generated?

wat> 👍 Indeed. And since random generation never fails, you’re sure to get your `msg` back as soon as the `value` it contains is generated.

me> And when I get my `NewValue` message with its value inside, all I need to do is use it to change my model. Makes sense. But the `dieGenerator` definition is *weird*! 😲

wat> Let’s dive in. First, we use a rather simple generator that the `Random` module gives us for free:

`Random.int : Int -> Int -> Generator Int`

me> Yes, I guess it takes a lower and a higher bound and generates an `Int` value that’s inside the bounds?

wat> Correct 😃 now let’s see if you recognize your old friend `map`

`Random.map : (a -> b) -> Generator a -> Generator b`

me> 🤔 Soooo, it’s one of the weird cases where `map` works with something that’s promised rather than something that’s contained?

wat> Exactly. A `Generator a` does not contain the `a` that it will generate in the future, so you couldn’t use a simple `case .. of` to get the value and work with it right here and now ; yet, with `Random.map` you can use that future value to make the `Generator b` you need.

me> Ok. Let me see if I get what’s happening in the transformation function:

`\intValue ->    case intValue of        1 -> One        2 -> Two        3 -> Three        4 -> Four        5 -> Five        6 -> Six        _ -> One`

wat> So?

me> We get the `intValue` (which is an `Int` since we’ve generated it with a `Generator Int`) and when it’s `1` we return a `One`, when it’s `2` we return a `Two`… why is there a `_ -> One` at the bottom though? We told `Random.int` that we wanted an `Int` between `1` and `6` didn’t we?

wat> Oh, that’s because the transformation function has no way to know about those bounds. All it knows is that the value will be an `Int`, and a `case .. of` instruction has to account for all possible values, so it needs a catch-all (`_`) to ward against that possibility, even though we know it’ll never arise. Also… let’s say we could have used `Random.uniform` instead for more clarity. I’ll let you have a look at the docs.

me> Oooooh, I see there’s also a `Random.andThen`… Are there cases when a `Generator` fails?

wat> Aha, silly human, just as `map` is not just for values that are already there, `andThen` is not just for failures… but that’s a story for another time.