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)

扫描二维码关注公众号,回复: 4875133 查看本文章

    /// 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/

猜你喜欢

转载自www.cnblogs.com/feng9exe/p/10256864.html
frp