【问题标题】:Elm - producing a list of random number changing with timeElm - 生成随时间变化的随机数列表
【发布时间】:2014-07-25 16:02:44
【问题描述】:

我试图让一列随机数每秒发生变化,但我收到不同的错误消息:

import Random

main = flow down 
[ asText (Random.range 0 100 (every second))  
, asText (Random.range 0 100 (every second))
]

给出一个解析错误。我的方括号[ 有什么问题?

Parse error at (line 5, column 1):
unexpected '['
expecting newline, spaces or end of input

缩进可能吗?

一旦我缩进,这个例子就会编译,但我只是得到<signal>而不是实际数字

main = flow down 
  [ asText (Random.range 0 100 (every second))  
  , asText (Random.range 0 100 (every second))
  ]

lift 用于信号?

最后,当我尝试使用 lift 时,它给了我其他的困惑

main = flow down 
  [ lift asText (Random.range 0 100 (every second))  
  , lift asText (Random.range 0 100 (every second))
  ]

错误消息是lift 的类型错误。

Type error on line 5, column 5 to 9:
       lift

  Expected Type: Signal Element
    Actual Type: Element

没有flow down 只是一个列表

如果我忘记流下来它仍然不合作:

main = lift asText
  [  (Random.range 0 100 (every second))  
  ,  (Random.range 0 100 (every second))
  ]

我收到一条错误消息,提示应为 _List

Type error between lines 5 and 7:
       [Random.range 0 100 (every second),
        Random.range 0 100 (every second)]

  Expected Type: _List
    Actual Type: Signal

?

我是否正确使用Random.range?我没有从原来的例子中改变它:

如何让它与liftflow down合作?

【问题讨论】:

    标签: random signals elm


    【解决方案1】:

    这是一个适用于 0.15 [编辑:和 0.16] 的答案,当前是 Elm 的最新版本。自从写了乔的答案以来,已对 Random 库进行了彻底检查,以使用纯随机数生成器。伪随机数是确定性的:每次运行始终相同,除非您更改初始种子。

    我们从导入开始:无聊但必要,然后使用 Random 库定义一些常量。

    import Graphics.Element exposing (flow, down, show, Element)
    import Time exposing (fps)
    import Random
    
    gen = Random.int 0 100
    gen2 = Random.pair gen gen
    seed0 = Random.initialSeed 42
    

    接下来我们定义一个状态类型,包含随机种子和要显示的数字。我以为我们想要两个;对于恒定长度的列表,请使用Random.list n gen。我们还使用记录构造函数语法(和两个“随机”数字)定义了一个初始状态。

    type alias State = {seed : Random.Seed, first : Int, second : Int}
    state0 = State seed0 36 89
    

    现在我们定义一个每秒运行一次的阶跃函数。在这里,我们剥离两个随机数并将它们与新种子一起存储。请注意,我们每次都使用一个新的种子,一个接一个地链接起来。

    step : a -> State -> State
    step _ state =
      let
        ((first, second), seed') = Random.generate gen2 state.seed
      in
        State seed' first second
    

    现在我们使用foldp 来引入状态,以实际运行该步进函数。

    state : Signal State
    state = Signal.foldp step state0 (fps 1)
    

    我们定义了一个纯渲染函数。这里没有信号。

    render : State -> Element
    render state =
        flow down [show state.first, show state.second]
    

    最后我们将渲染函数映射(以前提升)到状态。

    main = Signal.map render state
    

    如果您连接灰色框并删除插页式 cmets,您将获得一个有效的 Elm 0.15 程序。但请注意,它似乎是 CPU 密集型的。

    【讨论】:

    • 另外,如果您担心非实际随机的起始值,请定义state0 = State seed0 0 0 |> step ()
    【解决方案2】:

    这里发生了几件事:

    正如您所料,在第一部分中您遇到了编译器不喜欢的缩进问题。

    下一个示例之所以有效,是因为列表中的两件事实际上是信号。但是,这不是你想要的。相反,您想打印出符号。

    这里举一个简单的例子来提升Random.range

    import Random
    
    main = asText <~ (Random.range 0 10 (every second))
    

    这将每秒显示一个介于 0 和 1 之间的值。这与lift 的工作方式有关。它的类型是(a -&gt; b) -&gt; Signal a -&gt; Signal b。每次第二个参数的信号发生变化时,它都会使用该值运行指定的函数。

    因此,您尝试的第三件事的编译错误是抱怨函数flow 期望您的列表内容为Element,但它们实际上是Signal Element

    你在那里的最后一件事不起作用,因为lift 期望Signal 作为它的第二个参数,但你却给它一个[Signal]

    你真的想要这样的东西:

    import Random
    
    main = lift2 randomcolumn (Random.range 0 100 (every second)) (Random.range 0 100 (every second))
    
    randomcolumn x y = flow down [asText x,
                              asText y]
    

    http://share-elm.com/sprout/53d28d73e4b07afa6f983534

    希望这会有所帮助!

    【讨论】:

    • 也许你应该提到(&lt;~)是lift的中缀版本。也许提及 [floatList : Signal Int -&gt; Signal [Float]](library.elm-lang.org/catalog/evancz-Elm/0.12/Random#floatList) 和 combine : [Signal a] -&gt; Signal [a] 也很重要。尽管您的解释是恰当的,并且提取非信号函数并将其提升是更好的代码风格。
    猜你喜欢
    • 2016-05-16
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    相关资源
    最近更新 更多