我想在Haskell中学习FRP,但要确定要使用的库有点困难.许多似乎是死亡的尝试,有些似乎已经复活(例如最近在Yampa的活动).
根据我的阅读,似乎FRP有两种"种类":一侧是推拉式FRP(如Reactive-banana),另一侧是箭头式FRP(如Yampa).似乎在弗兰和弗里斯时代曾经有过一些"经典的FRP",但我没有发现其中的任何近期活动.
这两个(或三个)FRP真的是根本不同的方法吗?
其中一个是过时的理论而另一个是"未来的东西"?
或者它们是否必须并行发展,以满足不同的目的?
我是否列出了每个类别中最突出的图书馆,还是有其他选择要考虑(Sodium,Netwire等)?
我终于在J. Abrahamson的评论中看到了Evan Czaplicki的讲话.这非常有趣,并帮助我澄清了一些事情.我强烈推荐给发现这个问题的人.
我正在尝试使用Yampa进行一些基本的系统仿真,就像我在Simulink中所做的那样.在这种情况下,我想模拟这个simulink教程介绍的弹簧和阻尼系统.我写了以下信号函数来代表系统:
system = time >>> force >>> displacement
force = constant (m * g)
displacement = feedback (-) (velocity >>> integral) (gain $ k / m) 0
velocity = feedback (-) integral (gain $ c / m) 0
Run Code Online (Sandbox Code Playgroud)
当feedback函数创建一个基本的反馈回路,并像这样实现的:
feedback op a b b0 = loopPre b0 inner
where inner = arr (uncurry op) >>> a >>> (identity &&& b)
Run Code Online (Sandbox Code Playgroud)
哦,并且:
gain x = arr (*x)
Run Code Online (Sandbox Code Playgroud)
有了明显的正常数,我得到了一个非常不稳定的系统:

在我构建反馈循环或应用集成的方式中是否存在明显错误?
我现在正在学习Haskell和Yampa,并对重新启动函数有疑问.
reactimate :: IO a -- init
-> (Bool -> IO (DTime, Maybe a)) -- sense
-> (Bool -> b -> IO Bool) -- actuate
-> SF a b -- signal function
-> IO ()
Run Code Online (Sandbox Code Playgroud)
正如你在类型签名中看到的那样,sense函数的部分输出是函数当前和上一次调用之间的时间差.在我看到的例子中,这个时间差是在意义上"手动"计算的,使用IORef来保持前一次调用的值.
你必须使用外部状态跟踪时差这似乎很奇怪,为什么在重新计算功能中不进行这种计算?IORef是处理它的好方法吗?
我的意思是一阶约束
首先,我将通过箭头的一阶约束来解释我的意思:由于箭头desugar的方式,你不能使用箭头命令中预期箭头命令的本地绑定名称.
这是一个例子来说明:
proc x -> f -< x + 1desugars到arr (\x -> x + 1) >>> f并且类似地proc x -> g x -< ()将desugar到arr (\x -> ()) >>> g x,其中第二x是自由变量.该GHC用户指南解释了这一点,并说,当你的箭也是一个单子,你可以做的实例ArrowApply,并使用app来解决这个问题.proc x -> g x -<< ()变得像arr (\x -> (g x, ())) >>> app.
我的问题
Yampa accumHold用这种类型定义函数:a -> SF (Event (a -> a)) a.由于这个箭头的一阶限制,我正在努力编写以下函数:
accumHoldNoiseR :: (RandomGen g, Random …Run Code Online (Sandbox Code Playgroud) 我试图理解这个功能反应式编程是如何工作的,我遇到了一个问题.我正在尝试创建一个boid模拟,但是我开始慢慢地,我现在已经定义了一个boid作为一个起始位置并从一个位置到一个位置创建信号函数的函数,其中输入是点它正在走向,输出是当前位置:
type Position2 = Vector2 Float
boid :: Position2 -> SF Position2 Position2
boid s = loop (arr (uncurry seek) >>> integral >>> arr (^+^ s) >>> arr dup)
Run Code Online (Sandbox Code Playgroud)
seek函数需要两个输入(因为循环).当前位置和目标位置.然后它只是创建一个从当前位置指向目标位置的矢量,其幅度为50即速度.然后积分速度并添加起始位置.最后,信号被分成两部分,因此一个可以成为输出,另一个可以循环回到搜索功能.
现在我可以像这样定义boids:
aBoid = constant (vector2 500 500) >>> (boid (vector2 600 60))
bBoid = aBoid >>> (boid (vector2 3 4))
Run Code Online (Sandbox Code Playgroud)
这里aBoid寻求点(500,500)和bBoid寻求aBoid.
我的问题是,当我想要两个boid相互寻求时.当我这样做:
aBoid = bBoid >>> (boid (vector2 600 60))
bBoid = aBoid >>> (boid (vector2 3 4))
Run Code Online (Sandbox Code Playgroud)
该程序只是打印:ProgramName: <<loop>>我假设它意味着它进入无限循环.
我也试过使用这样的par函数:
sim :: SF …Run Code Online (Sandbox Code Playgroud)