cop*_*ton 7 haskell frp reactive-programming reactive-banana
我是反应性香蕉和FRP的新手,所以如果我遗漏了一些明显的东西,我会道歉.
对于我的项目(GDB/MI前端),我使用了响应式香蕉(版本0.6.0.0)用于GUI和前端逻辑模块.前者工作得很好,但对于后者我显然需要额外的组合器.
其中之一是zipE :: Event t a -> Event t b -> Event t (a, b).不幸的是,我能想到的只是NetworkDescription monad中的一个解决方案,它changes在事件类型中使用并且不是通用的:
zipE :: Event t Int -> Event t String -> NetworkDescription t (Event t (Int, String))
zipE ea eb = changes $ (,) <$> stepper 0 ea <*> stepper "" eb
Run Code Online (Sandbox Code Playgroud)
当然,我对此并不满意.因此,我想问一下如何在不使用的情况下实现通用的zipE函数changes(不鼓励用于非GUI目的).
其他尝试失败,例如
zipE :: Num a => Event t a -> Event t b -> Event t (a,b)
zipE ea eb = apply (stepper (0,) ((,) <$> ea)) eb
Run Code Online (Sandbox Code Playgroud)
导致元组的第一个元素移动一个 - 我猜是由于引入的"轻微延迟" stepper.但是我没有看到如何从没有stepper(或者accumB就此而言)的事件中获取行为,并且我没有看到如何将函数应用于没有行为的事件.总的来说,我不知道如何在泛型类型的情况下为步进器提供初始值.
Joh*_*n L 13
你的定义有困难,zipE因为它没有语义意义.如果考虑语义定义
Event a == [(Time, a)]
Event b == [(Time, b)]
Run Code Online (Sandbox Code Playgroud)
没有一种自然的方式来拉链它们,因为通常每个事件都会在不同的时间.
可以使用总和而不是产品来压缩它们.
zipE :: Event a -> Event b -> Event (Either a b)
zipE aE bE = (Left <$> aE) `mappend` (Right <$> bE)
Run Code Online (Sandbox Code Playgroud)
如果你真的需要有两个a与b在同一时间,合适的解决方案是创建一个Behavior是日积月累的一个或另一个,或合并Either如上流.
编辑:在合并流上累积的一种方法的示例(未经测试).其他实现也是可能的.这不会使两个事件同时发生,而是让您将当前状态与过去状态组合在一起,这样您就可以始终拥有最近可用的两个值Left和Right值.
currentAandB :: a -> b -> Event a -> Event b -> Event (a,b)
currentAandB a0 b0 aE bE = accumE (a0,b0) (mergefn <$> zipE aE bE)
where
mergefn (Left a) (_,b) = (a,b)
mergefn (Right b) (a,_) = (a,b)
Run Code Online (Sandbox Code Playgroud)
仍然需要为两个Event流提供初始值.可以这样想:如果你只有事件Event a,那么元组的第二部分应该有什么价值?
| 归档时间: |
|
| 查看次数: |
165 次 |
| 最近记录: |