Monad新解-FRP对比——ReactiveCocoa、RxSwift、Bacon以及背后的Functional
ReactiveX
Rx的Observable的本质就是一个Event Monad,即上下文(就是图文教程中包裹的盒子)为Event的一个Monad,这里的Event定义,可以对应语言的struct或者enum,包括了next、error和complete三个上下文即可。这里截取的是Swift语言的实现,map方法实现拆装箱(类似Optional,即Haskell的Maybe)
public enum Event<Element> {
/// Next element is produced.
case next(Element)
/// Sequence terminated with an error.
case error(Swift.Error)
/// Sequence completed successfully.
case completed
}
extension Event {
/// Maps sequence elements using transform. If error happens during the transform .error
/// will be returned as value
public func map<Result>(_ transform: (Element) throws -> Result) -> Event<Result> {
do {
switch self {
case let .next(element):
return .next(try transform(element))
case let .error(error):
return .error(error)
case .completed:
return .completed
}
}
catch let e {
return .error(e)
}
}
}
而Rx的subscribe方法就是一个解包,也就是Monad<Event>.map(),接收一个(Event) -> void的参数。或者使用更一般直观的三个参数onNext: (Element) -> Void、onError: (Error) -> Void、onCompleted: (Void) -> Void方法(在其他语言实践上,RxJS就是三个function参数,而RxJava为了支持Java7可以使用匿名内部类)
理论:
Monad Event <$> subscribe
示例:
let subscription = Observable<Int>.interval(0.3)
.subscribe { event in
print(event) // unwraped event
}
let cancel = searchWikipedia("me")
.subscribe(onNext: { results in
print(results)
}, onError: { error in
print(error)
})
Rx的Operator是Functor,也就是说(Event) -> Event,因此可以通过Monad不断bind你想要的组合子,直到最终符合UI控件需要的数据
理论:
Monad Event >>= map >>= concat >>= filter >>= map <$> subscribe
示例:
let subscription = primeTextField.rx.text // Observable<String>
.map { WolframAlphaIsPrime(Int($0) ?? 0) } // Observable<Observable<Prime>>
.concat() // Observable<Prime>
.filter { $0.isPrime } // Observable<Prime>
.map { $0.intValue } // Observable<Int>
Promise / Future
Promise本质上也是一个Monad,包裹的上下文就是resolve和reject。
你可能反驳说Promise.then(f)中的f,可以是value => value,而并不是一个被Promise包裹的类型啊。但是实际上,由于JavaScript类型的动态性,Promise.then中直接返回value类型是个语法糖罢了,实际上会处理为value => Promise.resolve(value)
Promise.resolve(1)
.then(v => v+1) //便捷写法罢了,返回的是resolved状态的Promise对象
.then(v => Promise.resolve(v+1)) //完整写法
.then(v => Promise.reject('error ' + v)) //想要返回rejected状态,无便捷方法
.catch(e => console.log(e)) // error 3
原理:
Monad Promise >>= then >>= then >>= catch >>= then
示例:
Promise.resolve(1)
.then(v => {
return v + 1; // 1
}.then(v => {
throw new Error('error'); //reject
}.catch(e => {
console.log(e); // error
return Promise.resolve(0);
}.then(v => {
console.log('end', v); // end 0
}
https://dreampiggy.com/2016/11/17/FRP简介—ReactiveCocoa、RxSwift、Bacon以及背后的Functional/
Monad新解-FRP对比——ReactiveCocoa、RxSwift、Bacon以及背后的Functional的更多相关文章
- ReactiveCocoa / RxSwift 笔记一
原创:转载请注明出处 ReactiveCocoa / RxSwift Native app有很大一部分的时间是在等待事件发生,然后响应事件,比如 1.等待网络请求完成, 2.等待用户的操作, 3.等待 ...
- RxSwift之路 1#Swift语法知识准备
RxSwift之路 1#Swift语法知识准备 在开始学习 RxSwift 之前,一定要对 Swift 相关语法有所了解,否则就很难理解为什么可以这样.关于 Swift 的学习其实只要看看 Swift ...
- Functor、Applicative 和 Monad(重要)
Functor.Applicative 和 Monad Posted by 雷纯锋Nov 8th, 2015 10:53 am Functor.Applicative 和 Monad 是函数式编程语言 ...
- ReactiveCocoa入门教程:第一部分
http://www.cocoachina.com/ios/20150123/10994.html 本文翻译自RayWenderlich,原文:ReactiveCocoa Tutorial--The ...
- 使用ReactiveCocoa实现iOS平台响应式编程
使用ReactiveCocoa实现iOS平台响应式编程 ReactiveCocoa和响应式编程 在说ReactiveCocoa之前,先要介绍一下FRP(Functional Reactive Prog ...
- [转]使用ReactiveCocoa实现iOS平台响应式编程
原文:http://www.itiger.me/?p=38 使用ReactiveCocoa实现iOS平台响应式编程 ReactiveCocoa和响应式编程 在说ReactiveCocoa之前,先要介绍 ...
- Scalaz(28)- ST Monad :FP方式适用变量
函数式编程模式强调纯代码(pure code),主要实现方式是使用不可变数据结构,目的是函数组合(composability)最终实现函数组件的重复使用.但是,如果我们在一个函数p内部使用了可变量(m ...
- FRP represents an intersection of two programming paradigms.
FRP represents an intersection of two programming paradigms. Functional programming Functional progr ...
- iOS Architecture Patterns
By Bohdan Orlov on 21 Mar 2016 - 0 Comments iOS FYI: Slides from my presentation at NSLondon are ava ...
随机推荐
- 使用idea开发工具,nginx服务部署Extjs6,SpringBoot项目到服务器
编译ExtJs文件 1.输入命令 2.开始编译 3.找到编译后的文件 E:\idea_project\BaiSheng_Model\fin-ui\build\production\Admin 4.将文 ...
- [PY3]——找出一个序列中出现次数最多的元素/collections.Counter 类的用法
问题 怎样找出一个序列中出现次数最多的元素呢? 解决方案 collections.Counter 类就是专门为这类问题而设计的, 它甚至有一个有用的 most_common() 方法直接给了你答案 c ...
- mariadb sequence
MariaDB 10.3 正式版推出后,有了像 Oracle.PostgreSQL 里的序列特性. 同时表字段AUTO_INCREMENT原特性还保持,但是sequence特性在某些特定情境还是很有用 ...
- NetMQ:.NET轻量级消息队列
前言 首先我现在是在一家游戏工作做服务端的,这几天我们服务端游戏做了整个底层框架的替换,想必做过游戏的也都知道,在游戏里面会有很多的日志需要记录,量也是比较大的:在没有换框架之前我们存日志和游戏运行都 ...
- 2017年11月30日 C#TreeNode递归&邮箱验证&新用户窗体
TreeNode递归 递归:自己调用自己一层一层的把数据找出来 TreeNode:可以创建多个节点 private void button1_Click(object sender, EventArg ...
- 工厂模式(Factory Pattern)
一.工厂模式(Factory Pattern)的介绍 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式.在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使 ...
- Error:Annotation processors must be explicitly declared now.
环境 Android Studio 3.0 Gradle 3.0.0 gradle 4.1 Error Error:Execution failed for task ':app:javaPreCom ...
- Oracle OCI操作UDT相关学习(二)
沿用 Oracle OCI操作UDT相关学习 一文中定义的类型和表. 1.更改数据 在sqldeveloper 中更新数据, update dxl.cust set addr.street='a11' ...
- csharp:DropDownComboxTreeView
using System; using System.Collections.Generic; using System.Text; using System.Drawing; using Syste ...
- 洛谷P2196 挖地雷(dp)
题意 题目链接 Sol 早年NOIP的题锅好多啊.. 这题连有向边还是无向边都没说(害的我wa了一遍) 直接\(f[i]\)表示到第\(i\)个点的贡献 转移的时候枚举从哪个点转移而来 然后我就用一个 ...