1. 2
  1.  

  2. 3

    This article uses the pre-0.17 style of defining a Native module. The up-to-date implementation of the module will look like this:

    var _user$project$Native_SecureRandom = function(){
      var getRandomInt = _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) {
        var randomInt = window.crypto.getRandomValues(new Uint32Array(1))[0]));
        callback(_elm_lang$core$Native_Scheduler.succeed(randomInt));
      });
      return {
        getRandomInt: getRandomInt
      };
    }();
    

    mgold has a pure Elm package known as elm-random-pcg, which is apparently a better random implementation. You can read more about that here

    Likewise, the documentation here also explains how to define a simpler, less crypto-safe Random implementation for 0.16. It also has some extra documentation on Native modules and why they are unsafe, for those interested.

    1. 2

      elm-random-pcg is not cryptographically secure as it states on it’s documentation page.

      The author updated his native module for elm 0.17 on github.

      1. 1

        Yep - i was just bringing it up as a related elm random module. The core random module is often called “not random enough” and often confuses beginners. Until a task was introduced, anyway.

        As far as i can see, there is no branch with valid native code for 0.17. On master at least, this file will not work and give you runtime errors if you attempt to use it. It is not valid native code for 0.17.

    2. 1

      This kinda sours me on the rest of the article:

      But for security-related applications it is completely opposite: you definitely don’t want anyone to be able to figure out your randomly generated private key. If we wanted to generate random values for cryptographic purpose, we definitely wouldn’t want the random generator to be so explicitly predictable.

      It incorrectly implies that deterministic randomness is incompatible with cryptography, when the truth is the exact opposite. It conflates being able to predict future values using the key with being able to recover the key given outputs; the latter is anathema to crypto, but the former is reasonable.

      1. 1

        Yes, a stream cipher is perfectly dependent and predictable based on the key, but that’s really just rearranging the problem. Where does the seed for your RNG come from in a functional world?

        1. 1

          Plausibly, a KDF and a user’s password. Of course, now the question is how you get the salt.

          I understand that you need an IO Something; I just really didn’t like the way the above paragraph tried (and IMO failed) to communicate that fact.

      2. 1

        Probably not the intended effect, but this article pretty thoroughly convinced me to not go anywhere near elm.

        1. 2

          Why?

          1. 2

            Something about making the hard things easy and the easy things impossible. Maybe it’s just me, but easy to use random numbers I just expect to be there.

            Same experience with most functional languages. They solve some problem I rarely have, in exchange for greatly complicating the things I do every day.

            1. 2

              Elm is at 0.17 and they really mean it. Saying the standard library is getting fleshed out would give you the false impression it has bones yet.

              1. 2

                This example is not an accurate reflection of Elm right now. Nobody needs to implement these modules like this. There is a much more robust way of communicating with JS via ports, which remove the need for any of that JS you see in there. You just subscribe and send.

                This is a full example of making a dice in 0.17, using the built in random implementation. Communicating the same via ports for a full crypto call requires only four extra lines of code from inside Elm.

                import Random
                import Html exposing (Html)
                import Html.Events exposing (onClick)
                import Html.App
                
                type alias Model = { faceValue : Int }
                
                type Msg = RollDice | SetDiceValue Int
                
                update : Msg -> Model -> (Model, Cmd Msg)
                update msg model = 
                  case msg of
                    RollDice ->
                      ( model, Random.generate SetDiceValue (Random.int 0 6) )
                    SetDiceValue newFaceValue ->
                      ( { model | faceValue = newFaceValue }, Cmd.none )
                
                view : Model -> Html Msg
                view model = 
                  Html.div 
                    []
                    [ Html.text (toString model.faceValue)
                    , Html.button [ onClick RollDice ] [ Html.text "roll dice!" ]
                    ]
                
                
                main = 
                  Html.App.program
                    { init = ( { faceValue = 1 }, Cmd.none )
                    , update = update
                    , view = view
                    , subscriptions = (\_ -> Sub.none)
                    }
                

                Here, we define two actions via RollDice and SetDiceValue Int. RollDice triggers the side-effectful promise (known as a Task), which will generate a random int between 0-6, then pass it as an argument to SetDiceValue, and feed it into the update loop.

                You can test this out on try-elm if you want to see.