Skip to content

Instantly share code, notes, and snippets.

@jehoshua02
Last active September 30, 2016 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jehoshua02/b4aa48d727ca57db890af82cb20a2ff6 to your computer and use it in GitHub Desktop.
Save jehoshua02/b4aa48d727ca57db890af82cb20a2ff6 to your computer and use it in GitHub Desktop.
Here's how I would have liked to get a random number in elm
randomItem : List a -> Maybe a
randomItem xs =
case xs of
[] ->
Nothing
_ ->
let
randomInt =
Random.int 0 ((List.length xs) - 1)
i =
Random.generate identity randomInt
in
getAt i xs
@rundis
Copy link

rundis commented Sep 30, 2016

Generating a random is a side effect. Side effects have to be handled by the Elm runtime. No getting around that. Like it or not. But in the bigger scheme of things that has a lot of benefits, even though in your particular case that is cumbersome.

So you'd need to do something like (which you might have already figured out for all I know):

module Main exposing (..)

import Html exposing (..)
import Html.Events exposing (onClick)
import Html.App as App
import Random


type alias Model =
    { myNum : Maybe Int }


type Msg
    = GenerateNum
    | RandomNum (Maybe Int)


init : ( Model, Cmd Msg )
init =
    ( Model Nothing, Cmd.none )



myList : List Int
myList =
    [1,2,3,4,5,6,7]


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GenerateNum ->
            (model, generateFromList myList)

        RandomNum num ->
            ({model | myNum = num }, Cmd.none)



generateFromList : List Int -> Cmd Msg
generateFromList xs =
    Random.int 0 (List.length xs - 1)
        |> Random.map (\num -> getAt num xs)
        |> Random.generate RandomNum


getAt : Int -> List a -> Maybe a
getAt idx xs =
    List.head <| List.drop idx xs


view : Model -> Html Msg
view model =
    div []
        [ h1 [] [ text (toString (Maybe.withDefault -1 model.myNum)) ]
        , button [ onClick GenerateNum ] [ text "Roll" ]
        ]


main : Program Never
main =
    App.program
        { init = init
        , view = view
        , update = update
        , subscriptions = \_ -> Sub.none
        }

@jehoshua02
Copy link
Author

@rundis yeah ok, but I don't have a program! I am strictly working with modules, types, functions, and tests at the moment. It's all logic with no UI.

https://github.com/jehoshua02/elm-sudoku/blob/puzzle-solve-tests/src/Sudoku/Puzzle.elm#L62

Should I be forced to have a Program / UI just to get a random number? What if I was shipping a package full of useful, lower-level, non-ui, non-program functions for use by a ui/program developer and one of my dozen functions featured some randomness, as part of it's core logic?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment