Ответ 1
Существуют разные способы сделать это. У каждого есть свои преимущества. Я дам вам три, которые я знаю с похожим примером для каждого.
1) Добавить ввод кода времени
Одна вещь, которую вы можете сделать, это добавить время на вкладку вашей программы. Пример крошечной программы, использующей текущее время каждую секунду для случайного числа:
import Time
import Time (Time, second)
import Text (asText)
import Mouse
import Signal
import Signal (Signal, (<~), (~))
import Random
import Random (Seed)
import Graphics.Element (Element)
randomInt : Seed -> Int
randomInt seed = seed |> (Random.generate <| Random.int 1 10) |> fst
otherInput : Signal (Int,Int)
otherInput = Mouse.position
timeSeed : Signal Seed
timeSeed = Random.initialSeed << round <~ Time.every second
inputs : Signal (Seed,(Int,Int))
inputs = (,) <~ timeSeed ~ otherInput
update : (Seed, (Int,Int)) -> (Int,Int) -> (Int,Int)
update (seed,(x,y)) (x',y') =
let num = randomInt seed
in (x-x'-num,y'-y+num) -- this update function is nonsense
main : Signal Element
main = asText <~ Signal.foldp update (0,0) inputs
Если вам нужно время как вход в любом случае, и пробуйте другие ваши входы, основанные на этом времени, это самый простой способ. (Если вы уже используете Time.fps
для этого, используйте Time.timestamp
, чтобы получить фактическое время с ним )
2) При запуске с сигналом
Если вам не требуется время в качестве входа в вашу программу, предыдущее решение не является идеальным. Вы можете предпочесть инициализировать свое состояние программы с указанием времени начала программы и не оставлять в стороне код времени в течение оставшейся части времени, когда программа запускается.
Это, вероятно, проще всего сделать с дополнительным пакетом . *. Используйте Signal.Time.startTime
, чтобы получить сигнал, который не гаснет, но только время начала программы в качестве начального значения. Используйте Signal.Extra.foldp'
, чтобы вы могли использовать начальное значение ваших входов.
import Time
import Time (Time, second)
import Text (asText)
import Mouse
import Signal
import Signal (Signal, (<~), (~))
import Random
import Random (Seed)
import Graphics.Element (Element)
import Signal.Extra as SignalE
import Signal.Time as Time
randomInt : Seed -> (Int,Seed)
randomInt seed = (Random.generate <| Random.int 1 10) |> fst
otherInput : Signal (Int,Int)
otherInput = Mouse.position
startTimeSeed : Signal Seed
startTimeSeed = Random.initialSeed << round <~ Time.startTime
inputs : Signal (Seed,(Int,Int))
inputs = (,) <~ startTimeSeed ~ otherInput
update (x,y) (seed,(x',y')) =
let (num,seed') = randomInt seed
in (seed',(x-x'-num,y'-y+num))
main : Signal Element
main = asText <~ SignalE.foldp' (snd >> update) identity inputs
* Я могу быть предвзятым, потому что я автор связанного пакета. Но я не знаю других пакетов, предлагающих ту же функциональность.
3) При запуске с портом
Если вы нашли предыдущее решение неудовлетворительным, потому что у вас есть этот не изменяющийся Signal
, чтобы добавить к вашему входу, это решение для вас. Здесь мы используем JavaScript interop, чтобы получить время запуска программы, и Elm примет его как постоянное значение (no Signal
). Код Elm выглядит так:
import Time
import Time (Time, second)
import Text (asText)
import Mouse
import Signal (Signal, (<~))
import Random
import Random (Seed)
import Graphics.Element (Element)
port startTime : Float
randomInt : Seed -> (Int,Seed)
randomInt seed = (Random.generate <| Random.int 1 10) |> fst
startTimeSeed : Seed
startTimeSeed = Random.initialSeed <| round startTime
update (x,y) (seed,(x',y')) =
let (num,seed') = randomInt seed
in (seed',(x-x'-num,y'-y+num))
main : Signal Element
main = asText <~ Signal.foldp update (startTimeSeed, (0,0)) Mouse.position
Итак, что здесь внизу? Вам нужно написать JavaScript. Вместо стандартного
<script>Elm.fullscreen(Elm.<YourModule>)</script>
вам нужно что-то подобное в вашем html файле:
<script>Elm.fullscreen(Elm.<YourModule>, {startTime: Date.now()})</script>
Если вы выберете этот способ, возможно, это хорошая идея использовать случайное число из JavaScript в качестве исходного семени. Я читал, что это более криптографически безопасно (отказ от ответственности: я мало знаю о криптографии). Таким образом, у вас будут port aRandomNumber : Int
и {aRandomNumber: Math.floor((Math.random() - 0.5) * 4294967295)}
.