mar*_*ngw 10 haskell frp reactive-programming
我正试图用Yampa-Framework模拟一个弹跳球:给定一个初始的x位置,高度和速度,球应该根据重力规则弹跳.信号功能以"提示 - 事件"作为输入,这个想法是"当球被倾斜时,它的速度应该加倍".
球反弹很好,但每次有小费事件时,该功能都会进入无限循环.我想我可能需要添加一个延迟(dSwitch,pre,notYet?),但我不知道如何.任何帮助,将不胜感激!
{-# LANGUAGE Arrows #-}
module Ball where
import FRP.Yampa
type Position = Double
type Velocity = Double
type Height = Double
data Ball = Ball {
height :: Height,
width :: Position,
vel :: Velocity
} deriving (Show)
type Tip = Event ()
fly :: Position -> (Height, Velocity) -> SF Tip (Ball, Event (Height,Velocity))
fly w0 (h0, v0) = proc tipEvent -> do
let tip = (tipEvent == Event ())
v <- (v0+) ^<< integral -< -10.0
h <- (h0+) ^<< integral -< v
returnA -< (Ball h w0 v,
if h < 0 then Event (0,(-v*0.6))
else if tip then Event (h, (v*2))
else NoEvent)
bounce w (h,v) = switch (fly w (h,v)) (bounce w)
runBounce w (h,v) = embed (bounce 10 (100.0, 10.0)) (deltaEncode 0.1 [NoEvent, NoEvent, NoEvent, Event (), NoEvent])
Run Code Online (Sandbox Code Playgroud)
编辑:我设法通过在尖端发生时反馈旗帜来避免无限循环,但仍然感觉不是正确的方法...
fly :: Position -> (Height, Velocity, Bool) -> SF Tip (Ball, Event (Height,Velocity,Bool))
fly w0 (h0, v0, alreadyTipped) = proc tipEvent -> do
let tip = tipEvent == Event () && (not alreadyTipped)
v <- (v0+) ^<< integral -< -10.0
h <- (h0+) ^<< integral -< v
returnA -< (Ball h w0 v,
if h < 0 then Event (0,(-v*0.6), False)
else if tip then Event (h, (v*2), True)
else NoEvent)
bounce w (h,v,alreadyTipped) = switch (fly w (h,v,alreadyTipped)) (bounce w)
Run Code Online (Sandbox Code Playgroud)
经过几天的黑客攻击,我想我找到了答案。技巧是将切换事件延迟到下一个时间点,以便在“旧”倾斜事件消失时发生notYet切换(以及对 的递归调用)。fly该second函数确保只有结果元组的第二部分(Ball, Event (..))将被传递notYet。这消除了无限循环,但也改变了语义:现在切换发生在一个“时间步长”之后,这反过来又导致不同的速度。
这个 Yampa 的东西实际上相当不错,遗憾的是没有太多文档可找到。我仍然无法找出pre和iPre函数的用途,我认为它们可以在类似的上下文中使用。
fly :: Position -> (Height, Velocity) -> SF Tip (Ball, Event (Height,Velocity))
fly w0 (h0, v0) = proc tipEvent -> do
let tip = tipEvent == Event ()
v <- (v0+) ^<< integral -< -10.0
h <- (h0+) ^<< integral -< v
returnA -< (Ball h w0 v,
if h < 0 then Event (0,-v*0.6)
else if tip then Event (h, v*2)
else NoEvent)
bounce w (h,v) = switch (fly w (h,v) >>> second notYet) (bounce w)
Run Code Online (Sandbox Code Playgroud)