Elm - 生成一个随时间变化的随机数列表

5
我试图创建一个每秒钟更改的随机数字列,但是我遇到了不同的错误消息:
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”,只是一个列表

如果我忘记了“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配合使用?

2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
5
这里有一个适用于0.15 [EDIT:和0.16]版本的答案,目前是Elm的最新版本。自从Joe回答后,Random library已经完全更新为使用纯随机数生成器。伪随机数是确定性的:除非您更改初始种子,否则每次运行都是相同的。

我们从导入开始:很无聊但必要,然后使用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]
最后,我们将渲染函数(原名为lift)映射到状态上。
main = Signal.map render state
如果你将灰色框拼接在一起并删除中间的注释,你将得到一个可工作的Elm 0.15程序。但请注意,它似乎对CPU要求较高。

另外,如果您担心起始值不是真正随机的,请定义state0 = State seed0 0 0 |> step() - mgold

3

这里发生了几件事情:

就像你预料的那样,在第一部分中,你有一个缩进问题,编译器不喜欢。

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

这里是举例说明如何使用Random.range

import Random

main = asText <~ (Random.range 0 10 (every second))
每秒钟都会显示一个0到1之间的值。这与lift的工作方式有关。它的类型是(a -> b) -> Signal a -> 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]

这个链接或许能帮到您!

希望这能对您有所帮助!


1
也许你应该提到(<~)是lift的中缀版本。或许还有必要提到floatList:Signal Int-> Signal [Float]combine:[Signal a]-> Signal [a]。虽然你的解释是恰当的,从代码风格上来说提取一个非信号函数并将其进行lift更好。 - Apanatshka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,