What I mean by first-order constraint
First, I'll explain what I mean by first-order constraint on arrows: Due to the way arrows desugar, you cannot use a locally bound name where an arrow command is expected in the arrow do-notation.
Here is an example to illustrate:
proc x -> f -< x + 1
desugars to arr (\x -> x + 1) >>> f
and similarly proc x -> g x -< ()
would desugar to arr (\x -> ()) >>> g x
, where the second x
is a free variable. The GHC user guide explains this and says that when your arrow is also a monad you may make an instance of ArrowApply
and use app
to get around this. Something like, proc x -> g x -<< ()
becomes arr (\x -> (g x, ())) >>> app
.
My Question
Yampa defines the accumHold
function with this type: a -> SF (Event (a -> a)) a
.
Due to this first-order limitation of arrows, I'm struggling to write the following function:
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
The definition above doesn't work because n
is not in scope after desugaring.
Or, similarly this function, where the first part of the pair to SF
is meant to be the initial value passed to accumHold
accumHold' :: SF (a,Event (a -> a)) -> a
accumHold' = ...
Is there some combinator or trick that I'm missing? Or is it not possible to write these definitions without an ArrowApply
instance?
tl;dr: Is it possible to define accumHoldNoiseR :: (RandomGen g, Random a) => (a,a) -> g -> SF (Event (a -> a)) a
or accumHold' :: SF (a,Event (a -> a)) -> a
in yampa?
Note: There is no instance of ArrowApply
for SF
. My understanding is that it doesn't make sense to define one either. See "Programming with Arrows" for details.