Как добавить вторую копию к этому примеру?
Я новичок в Elm и смотрю на следующий пример (обратите внимание, что это под новой архитектурой 0.17, где Action теперь Command): http://elm-lang.org/examples/random
Существует следующий вызов, чтобы добавить вторую фигуру к примеру, так что одним нажатием кнопки катит новое значение для каждого штампа. Моя идея состоит в том, чтобы изменить модель на наличие двух отдельных значений, по одному для каждой матрицы, ала
type alias Model =
{ dieFace1 : Int
, dieFace2 : Int
}
Это работает нормально, пока я не доберусь до блока обновления. Я не уверен, как обновить генератор случайных чисел, чтобы создать два значения. Эта функция немного сбивает меня с толку.
type Msg
= Roll
| NewFace Int Int
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Roll ->
**(model, Random.generate NewFace (Random.int 1 6))** <-- not sure what to do here
NewFace newFace1 newFace2 ->
(Model newFace1 newFace2, Cmd.none)
Документация для функции Random.generate немного светлая -
generate: (a → msg) → Генератор a → Cmd msg
Создайте команду, которая будет генерировать случайные значения.
Это даже правильный подход к обработке двух кубиков, или есть лучший способ? Я влю, ну, пожалуйста, будь милым :)
Ответы
Ответ 1
Random.int
- это примитивный генератор, который дает вам один случайный int. Вам нужен генератор, который дает вам ровно два случайных числа.
Генераторы случайных чисел могут быть созданы из более примитивных генераторов для создания более сложных генераторов. К счастью, у Elm есть такая функция Random.pair
которая позволяет вам указать, какие два генератора вы хотите для каждой части кортежа.
Пусть вытащите генератор штампа в его собственную функцию, чтобы избежать повторения:
dieGenerator : Random.Generator Int
dieGenerator =
Random.int 1 6
Теперь мы можем построить еще один генератор, который дает нам случайное значение пары die:
diePairGenerator : Random.Generator (Int, Int)
diePairGenerator =
Random.pair dieGenerator dieGenerator
Поскольку мы имеем дело с кортежем ints, давайте обновим ваше Msg
определение NewFace Int Int
до NewFaces (Int, Int)
. Это позволит вашему Roll
механизму быть красивым и чистым:
Roll ->
(model, Random.generate NewFaces diePairGenerator)
Если вы хотите попробовать выйти за рамки этого, подумайте о том, что потребуется, чтобы можно было прокатить любое количество штампов. Возьмите эту идею построения сложных генераторов из более примитивных генераторов и используйте документацию для модуля Random
мы руководство.
Ответ 2
Один из подходов - использовать batch
например https://gist.github.com/davidchase/40c27042bccfb00d786af0360b5bc3ea.
Другим является использование Random.pair
или Random.list
если вам нужно больше 2:
import Html exposing (..)
import Html.App as Html
import Html.Events exposing (..)
import Html.Attributes exposing (..)
import Random
main : Program Never
main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ dieFaces : (List Int)
}
-- http://stackoverflow.com/questions/23199398/how-do-i-get-a-list-item-by-index-in-elm#comment56252508_23201661
get : Int -> List a -> Maybe a
get n xs = List.head (List.drop n xs)
-- http://rundis.github.io/blog/2016/elm_maybe.html
getOrOne : Int -> List Int -> Int
getOrOne n xs = Maybe.withDefault 1 (get n xs)
init : (Model, Cmd Msg)
init =
(Model [1, 1], Cmd.none)
-- UPDATE
type Msg
= Roll
| NewFace (List Int)
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Roll ->
(model, Random.generate NewFace (Random.list 2 (Random.int 1 6)))
NewFace newFace ->
(Model newFace, Cmd.none)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
-- VIEW
view : Model -> Html Msg
view model =
div []
[ img [ src ("/img/Alea_" ++ toString (getOrOne 0 model.dieFaces) ++ ".png")] []
, img [ src ("/img/Alea_" ++ toString (getOrOne 1 model.dieFaces) ++ ".png")] []
, button [ onClick Roll ] [ text "Roll" ]
]
и еще один https://github.com/jcollard/random-examples/blob/master/src/Dice.elm
Ответ 3
Помимо изменений, описанных в принятом ответе @ChadGilbert, мне также пришлось менять NewFaces
обновления NewFaces
(используя elm 0.18.0
).
NewFaces newFaces ->
let
(newFace1, newFace2) = newFaces
in
(Model newFace1 newFace2, Cmd.none)