Seija
首页
Travellings
登录
注册
首页
文章
FRP系统的设计
### 目标 最终想要的效果如下: ```Haskell main::Button -> Text -> IO () main btn text = do (btn_ev,_) <- handler btn b <- foldBehavior 0 (\(n,_) -> n + 1) btn_ev attachText text {text:b} ``` 这段代码的意思是点击一次按钮Text上的文字就加一.
这里变得复杂的时候没有`reflex`好的一点是没法利用Lazy特性和`RecursiveDo`这种骚东西减少代码. `RecursiveDo`可以让我们使用下面才会定义的变量. ``` -- Required extension for rec style blocks -- {-# LANGUAGE RecursiveDo #-} rec let ev1 = f2 <$> ev2 d1 <- widgetHold (w1Init) (w1 <$> ev1) ev2 <- viewD1Widget d1 ```
在FRP这套系统中几乎所有的逻辑都在`Event`的变换中. 如下面的例子所示所示Event通过fmap可以不停的变换并嵌入逻辑,最后会组成一棵Event的树,树的最后的子节点会发射到Behavior身上. 而Behavior会绑定到具体需要数据的地方,例如按钮上的文字,角色的移动方向等等等等. ```Haskell main::IO () main = do a::Event Int <- mkEvent 0 let a1::Event Int = a <$> (+ 1) let b::Event String = a <$> (\n -> "b:" <> toString n) strb <- hold "" b inta1 <- hold 0 a1 return () ``` 举个例子,玩家点击`D`键,会有一个值为`(true,'D')`的`Event (Bool,Char)`Bool代表是按下还是抬起`Char`表示哪个键. ,我们通过一个fmap可以把它变换为`Event MoveState`,MoveState是个枚举有五个值`MoveLeft` `MoveRight` `MoveUp` `MoveDown` `Idle`. 我们把"WASD"键抬起全都对应为`Idle`,按下的时候映射为具体的方向.那么玩家的方向`Behavior`即可以根据按钮更新了,然后我们再到每帧都在`Tick`的事件中去根据方向更新玩家的位置`Behavior`再将玩家的位置`Behavior`绑定到图片的位置属性上. 那么就能够实现玩家的移动功能. ### 实现思路 先描述一下前提条件,引擎底层是Rust,会使用javascript引擎,然后会通过purescript编译器编译为javascript. 再来一个例子讨论一下`GC`和`Event树`构建的问题. ```Haskell import XXX.GlobalEventType as E main::GameM () main = do tickEvent <- getGlobalEvent E.Tick initView tickEvent return () data Dir = None | Left | Right initView::Event Float -> GameM () initView eTick = do (eLeft, _ ) <- mkButton {text:"Left"} (eRight, _ ) <- mkButton {text:"Right"} let dirEv = leftmost [eLeft $> Left,eRight $> Right] bDir <- hold None dirEv eDir <- tag bDir eTick bValue <- foldBehavior 0 upValue eDir return () where upValue num None = num upValue num Left = num - 1 upValue num Right = num + 1 ``` 如果initView只是个普通函数的话,那么里面的Event和behavior就会被GC掉.
DNMD,这样看起来变的更难了
* 思路1 每个事件的事件源作为Root由Rust持有,然后后续的事件逐级挂到事件源的后面,由此所有的事件都会通过事件源被持有引用。然后闭包引用的变量也会由于事件被持有引用。 * 思路2 关于Behavior,没有挂载事件的 Behavior可以称之为常量Behavior,常量Behavior想办法直接优化成常量 * 思路3 UI节点看起来可以不使用类似VDOM的技术,将UI节点从父级逐级创建出来,那么UI节点也是一个被持有引用的树,UI节点上的Event也就可以间接被持有引用。 * 问题1 如何控制UI节点的切换? 会不会造成GC问题?
登录
登录
注册
最热文章
引擎中Template DSL的设计思考总结
10-19
ReaderT 设计模式
04-23
非主流引擎开发不出来 (n+1) : purescript侧结构设计
04-04
FRP系统的设计
03-17
非主流引擎开发不出来 (1) : 轻骨架
02-11
非主流引擎开发不出来 (0) : 引擎定位
12-09
Rust的ECS库specs
11-20
Haskell类型类高级扩展详细说明
05-31
CMake 速览
05-29
尼采导读:超人与永恒轮回
02-24
为什么elm的结构并不是最合理的?
02-20
React速览
02-20
尼采命运之爱
02-18
AspNetCore 速览
02-17
由Haskell和面向对象引出的关于抽象的思考
12-26
二进制文件压缩工具upx
12-24
Reflex介绍
12-17
Web的前端渲染和WebApi
12-16
前端FRP框架深度踩坑
12-16
Yesod - RESTful (11)
12-16
链接
github
gitee