我所指的一阶限制
首先,我将解释一下我所说的箭头上的一阶限制: 由于箭头展开的方式,您无法在箭头do-notation中期望箭头命令的地方使用局部绑定名称。
这里有一个例子可以说明:
proc x -> f -< x + 1
展开为 arr (\x -> x + 1) >>> f
,类似地,proc x -> g x -< ()
将展开为 arr (\x -> ()) >>> g x
,其中第二个 x
是自由变量。 GHC用户指南 解释了这一点,并表示当您的箭头也是monad时,您可以创建 ArrowApply
实例并使用 app
来解决此问题。例如,proc x -> g x -<< ()
变成了 arr (\x -> (g x, ())) >>> app
。
我的问题
Yampa使用以下类型定义 accumHold
函数: a -> SF (Event (a -> a)) a
。
由于箭头的这个一阶限制,我很难编写下面的函数:
accumHoldNoiseR :: (RandomGen g, Random a) => (a,a) -> g -> SF (Event (a -> a)) a
accumHoldNoiseR r g = proc f -> do
n <- noiseR r g -< ()
accumHold n -< f
上面的定义不起作用,因为在desugaring后,
n
不在作用域内。或者,类似地,对于这个函数,
SF
对应的一对中的第一个值应该是传递给accumHold
的初始值。accumHold' :: SF (a,Event (a -> a)) -> a
accumHold' = ...
有没有组合器或技巧我漏掉了?或者是不可能在没有
ArrowApply
实例的情况下编写这些定义吗?
tl;dr:是否可以定义accumHoldNoiseR :: (RandomGen g, Random a) => (a,a) -> g -> SF (Event (a -> a)) a
或accumHold' :: SF (a,Event (a -> a)) -> a
在yampa中?
注意:SF
没有ArrowApply
实例。我的理解是也不可能定义一个。有关详细信息,请参见"Programming with Arrows"。
ArrowApply
,但解决这个问题的一种方法是问问自己,如果没有一阶限制,你认为你的代码应该展开成什么样子。 - Gabriella Gonzalez-<<
需要一个ArrowApply
实例,因此在这里没有意义(即,您不能将SF
变成一个单子)。 - Jason Dagit