【问题标题】:How to let a random amount of time pass with Yampa如何使用 Yampa 让随机的时间过去
【发布时间】:2021-10-04 15:19:29
【问题描述】:

我正在尝试使用 Yampa 编写一个简单的 FRP 示例,而不是等待 2 秒(如此处:https://wiki.haskell.org/Yampa/reactimate)将在一定范围内等待随机时间。我尝试了多种不同的方法来以某种方式将 randomRIO 函数放入信号函数中,但无法真正掌握我应该做什么。 我的意图是像这样替换 twoSecondsPassed 函数:

randomTimePassed :: SF () Bool
randomTimePassed = time >>> arr (\x -> x < randomRIO (0, 10))

但由于类型不匹配,这似乎不起作用。 编译器输出:

* Couldn't match type `m0 a0' with `Double'
  Expected: SF Time Bool
    Actual: SF (m0 a0) Bool
* In the second argument of `(>>>)', namely
    `arr (\ x -> x < randomRIO (0, 10))'
  In the expression: time >>> arr (\ x -> x < randomRIO (0, 10))
  In an equation for `randomTimePassed':
      randomTimePassed = time >>> arr (\ x -> x < randomRIO (0, 10))

任何正确方向的指针都将不胜感激,因为我对 Yampa 很陌生,似乎找不到合适的文档来帮助我。

【问题讨论】:

    标签: haskell frp yampa


    【解决方案1】:

    randomRIO (0,10) 的类型是(在您使用时专门化)IO Double,但您要替换的 2 的类型只是 Double。此外,您不能在 yampa SF 中执行 IO 操作。

    您需要做的是在SF 之外生成您的号码(或者可能为您的号码生成一个生成器)并将其作为参数传递。例如,你可以写:

    someTimePassed :: Double -> SF () Bool
    someTimePassed t = time >>> arr (\x -> x < t)
    
    main = do
      t <- getCurrentTime
      timeRef <- newIORef t
      randTime <- randomRIO (0, 10)
      reactimate initialize (sense timeRef) actuate (someSecondsPassed randTime)
    

    如果您需要多个随机数,则需要传递一个随机数生成器。您可以使用例如getStdGen 生成一个。此外,与其编写自己的SF 来使用它,不如将它传递给occasionally 之类的东西,它每隔一段时间就会产生事件。

    【讨论】: