相互に依存するワイヤvelocity
を使用して、オブジェクトを壁から跳ね返らせようとしています。location
単純な 1 次元の例は次のようになります。
{-# 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
ていると、「意図したとおりに」機能する可能性があります。
「ブルートフォース」ソリューションに頼らずに修正する方法の説明と提案が必要です。