Haskell 正确使用Netwire(5)

Haskell 正确使用Netwire(5),haskell,frp,netwire,Haskell,Frp,Netwire,我一直想给FRP打一针,昨天我终于咬紧牙关,尝试了一下,开始使用Netwire 5(这本身就是一个相当随意的选择,但我必须从某个地方开始!)。我已经设法做到了“代码有效”这一点,但我注意到了一些模式,我不确定这些模式是否是库的预期使用方式的一部分,或者它们是否是我在某个地方做错了什么的症状 我从开始,这足以让我很容易地启动和运行--我现在有了一个由简单的“递增数字”电线控制的旋转立方体: 当按下“Esc”时,应用程序将退出,使用中提供的导线: 它们之间的一个重要区别是,spin从不禁止——它应该

我一直想给FRP打一针,昨天我终于咬紧牙关,尝试了一下,开始使用Netwire 5(这本身就是一个相当随意的选择,但我必须从某个地方开始!)。我已经设法做到了“代码有效”这一点,但我注意到了一些模式,我不确定这些模式是否是库的预期使用方式的一部分,或者它们是否是我在某个地方做错了什么的症状

我从开始,这足以让我很容易地启动和运行--我现在有了一个由简单的“递增数字”电线控制的旋转立方体:

当按下“Esc”时,应用程序将退出,使用中提供的导线:

它们之间的一个重要区别是,
spin
从不禁止——它应该总是返回一些值——而
应该退出
始终禁止;直到按键真正按下,在这种情况下,我退出应用程序

让我不安的是我最终不得不使用这些电线。现在,它看起来像这样:

(wt', spinWire') <- stepWire spinWire st $ Right undefined
((qt', quitWire'), inp'') <- runStateT (stepWire quitWire st $ Right undefined) inp'

case (qt', wt') of
  (Right _, _) -> return ()
  (_, Left _)  -> return () -- ???
  (_, Right x) -> --do things, render, recurse into next frame
单步走这条线给了我一个更合理的返回值——如果它是
,我可以退出,否则我就有数据要处理。它还暗示了比我原来的方法更高程度的可组合性


不过,我仍然必须将
Right undefined
作为输入传递给这条新的线路。诚然,现在只有一个,但我仍然不确定这是否是正确的方法。

在程序的最高层,您将有一些(缩写)类型的导线
导线a b
。这需要传递
a
类型的内容,并且每次执行步骤时,它都会返回
b
类型的内容。例如,对于游戏来说,
a
b
可以是某种
WorldState
,对于物理模拟器来说也可以是
[刚体]
。在我看来,在顶层通过
Right undefined
是可以的

也就是说,您忽略了输入导线的重要
备选
实例
Wire a b
。它提供了一个操作员
,其工作方式非常好:

假设我们有两条电线:

w1 :: Wire a b
w2 :: Wire a b
如果w1抑制,则

w1 <|> w2 == w2
当您按下
F
时,您将以两倍的速度旋转

如果您想在按下按钮后更改导线的语义,您必须更具创造性,但不能太多。如果你的电线表现不同,那就意味着你在做某种切换。最重要的是需要你去做

这是一条电线,在按下给定键之前,它的作用类似于身份线,然后将永远禁止:

trigger :: GLFW.Key -> GameWire a a
trigger key =
  rSwitch mkId . (mkId &&& ((now . pure mkEmpty . keyPressed key) <|> never))

每当你点击
F

时,这将在向前和向后之间切换微调器。我倾向于在我的连线中不使用效果。事件被传递到“主线”,而monad是多态的。我认为我的答案和也有帮助
w1 :: Wire a b
w2 :: Wire a b
w1 <|> w2 == w2
w1 <|> w2 == w1
spin :: (HasTime t s, Monad m) => Wire s e m a GL.GLfloat
spin = integral 0 . (10 . keyPressed GLFW.Key'F <|> 5)
trigger :: GLFW.Key -> GameWire a a
trigger key =
  rSwitch mkId . (mkId &&& ((now . pure mkEmpty . keyPressed key) <|> never))
spin :: (HasTime t s, Monad m) => Wire s e m a GL.GLfloat
spin = integral 0 . spinSpeed
  where
    spinSpeed = 5 . trigger GLFW.Key'F --> 
                -5 . trigger GLFW.Key'F -->
                spinSpeed