Monad新解-FRP对比——ReactiveCocoa、RxSwift、Bacon以及背后的
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/ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |