zoukankan      html  css  js  c++  java
  • 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/

  • 相关阅读:
    数据库完整性约束
    系统介绍
    全栈性能测试修炼宝典--Jmeter实战(一)
    数据驱动(四)
    数据驱动(五)
    数据驱动(三)
    数据驱动(二)
    数据驱动(一)
    Robot Framework 三种测试用例模式
    sublime text---注释
  • 原文地址:https://www.cnblogs.com/feng9exe/p/10256864.html
Copyright © 2011-2022 走看看