我正在尝试使用相互依赖的电线使物体从墙壁上velocity
反弹location
。简单的一维示例如下所示:
{-# 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
会使它“按预期”工作。
我想要一个解释,并建议如何在不诉诸“蛮力”解决方案的情况下解决它。