【问题标题】:netwire: dealing with laziness(?) in mutually dependent wiresnetwire:处理相互依赖的电线中的懒惰(?)
【发布时间】:2015-01-19 00:02:37
【问题描述】:

我正在尝试使用相互依赖的velocitylocation 电线使物体从墙上反弹。简单的一维示例如下所示:

{-# LANGUAGE Arrows #-}
import Prelude hiding ((.), id)
import Control.Wire
import FRP.Netwire
import Control.Monad.IO.Class

-- location -> (corrected-location, did-bounce)
-- "reflect" location back behind the border and indicate the bounce
checkW :: (HasTime t s) => Wire s () IO Double (Double, Bool)
checkW = mkSF_ check
  where
  check loc
    | loc < 0   = (-loc,  True)
    | loc > 1   = (2-loc, True)
    | otherwise = (loc,   False)

-- did-bounce -> velocity, initial velocity in the argument
velW :: Double -> Wire s () IO Bool Double
velW iv = mkSFN $ \bounce -> (iv, velW (if bounce then -iv else iv))

-- produce tuple (location, velocity)
locvelW :: (HasTime t s) => Wire s () IO a (Double, Double)
locvelW = proc _ -> do
  rec (loc, bounce) <- (checkW . integral 0.5) -< vel
      vel <- (velW 0.3) -< bounce
  returnA -< (loc, vel)

main :: IO ()
main = testWireM liftIO clockSession_ locvelW

如果我运行这个,在第一次反弹速度开始每一步在负值和正值之间翻转

我知道我可以通过向速度线发出信号来“修复”它,根据我反弹的边界使速度为负数或正数。有用。但我想了解为什么我看到这种行为,我知道翻转应该只发生一次,因为我明确地将对象推到边框的另一侧。我怀疑懒惰在这里发挥了作用,也许战略性地放置seq 会使它“按预期”工作。

我想要一个解释,并建议如何在不诉诸“蛮力”解决方案的情况下解决它。

【问题讨论】:

    标签: haskell lazy-evaluation netwire


    【解决方案1】:

    此行为是由 velW 中的一个简单逻辑错误引起的。 velW 在弹跳时不会改变速度,它只是在下次计算速度时改变初始速度;他们都应该改变。这是一个正确的版本。

    -- did-bounce -> velocity, initial velocity in the argument
    velW :: Double -> Wire s e m Bool Double
    velW iv = mkSFN $ \bounce -> let vel = if bounce then -iv else iv in (vel, velW vel)
    

    懒惰在这里无法发挥作用。惰性会影响计算发生的时间,但不会影响计算的含义。纯计算不受副作用影响,因此其结果不依赖于何时计算。

    【讨论】:

      猜你喜欢
      • 2013-09-02
      • 1970-01-01
      • 2014-09-08
      • 2015-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-19
      相关资源
      最近更新 更多