JHHK

欢迎来到我的个人网站
行者常至 为者常成

19_02、函数式编程(二)

目录

函数式编程(一)

// 一、函数式编程
func funtionalProgramming() -> Void {
    
    /**
     函数式编程(Funtional Programming)
     
     一、函数式编程(Funtional Programming,简称FP)是一种编程范式,也就是如何编写程序的方法论
         主要思想:把计算过程尽量分解成一系列可复用函数的调用
         主要特征:函数是“第一等公民”
            函数与其他数据类型一样的地位,可以赋值给其他变量,也可以作为函数参数、函数返回值
     
     
     二、函数式编程最早出现在LISP语言,绝大部分的现代编程语言也对函数式编程做了不同程度的支持,比如
        Haskell、JavaScript、Python、Swift、Kotlin、Scala等
     
     三、函数式编程中几个常用的概念
        Higher-Order Function、Function Currying
        Functor、Applicative Functor、Monad
        
     四、参考资料
         http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
         http://www.mokacoding.com/blog/functor-applicative-monads-in-pictures
     */
    
    
    //1、传统方式
    do{
        print("-----1-----")
        func add(_ num1:Int,_ num2:Int)->Int{
            num1 + num2
        }
        
        let num = add(3, 8)
        print(num)//8
    }
    
    
    //2、函数式
    do{
        print("-----2-----")
        func add(_ num1:Int) -> (Int) -> Int{
            return {
                (num2:Int) ->Int in
                return num1 + num2
            }
        }
        
        let num = add(3)(5)
        print(num)//8
    }
    
    
    //3、函数式简写
    do{
        print("-----3-----")
        func add(_ num:Int) -> (Int)->Int{ { num + $0 } }
        
        let fn = add(3)
        let num = fn(5)
        print(num)// 8
        
        let num1 = fn(6)
        print(num1)// 9
    }
}

函数式编程(二)

//二、函数式编程
//定义一个中缀运算符
infix operator >>> : AdditionPrecedence
func >>><A, B, C>(_ f1: @escaping (A) -> B,
                  _ f2: @escaping (B) -> C) -> (A) -> C {
    { f2(f1($0)) }
}
func funtionalProgramming2() -> Void {
    
    func add(_ v: Int)      ->  ((Int) -> Int)   { { $0 + v } }
    func sub(_ v: Int)      ->  ((Int) -> Int)   { { $0 - v } }
    func multiple(_ v: Int) ->  ((Int) -> Int)   { { $0 * v } }
    func divide(_ v: Int)   ->  ((Int) -> Int)   { { $0 / v } }
    func mod(_ v: Int)      ->  ((Int) -> Int)   { { $0 % v } }
    
    
    let fn = add(3) >>> multiple(5) >>> sub(1) >>> mod(10) >>> divide(2)
    
    let result = fn(4)
    print(result)
}

高阶函数(Higher-Order Function)

//三、 高阶函数(Higher-Order Function)
prefix func ~<A,B,C>( _ fn: @escaping (A,B)->C ) -> (A) -> (B) -> C {
    { a in
        { b in
            fn(a,b)
        }
    }
}
func funtionalProgramming3() -> Void {
    
    /**
     高阶函数是至少满足下列一个条件的函数:
        接受一个或多个函数作为输入(map、filter、reduce等)
        返回一个函数
     就是函数作为参数或返回值
     
     FP中到处都是高阶函数
     */
    
    //1、高阶函数
    do{
        print("-----1-----")
        func add(_ v: Int) ->
        ((Int) -> Int) {
            { $0 + v }
        }

        let num = add(5)(4)
        print(num)//9
    }
    
    
    //2、柯里化(Currying)加法 两个参数
    do{
        print("-----2-----")
        
        /**
         什么是柯里化?
         将一个接受多参数的函数变换为一系列只接受单个参数的函数
         add(10,20)
         add(10)(20)
         */
        func add(_ v1: Int, _ v2: Int) -> Int {v1 + v2}
        let num = add(10, 20)
        print(num)//30
        
        
        //柯里化
        func curryingAdd(_ v: Int)  ->   ((Int) -> Int)  {
            { $0 + v }
        }
        let curringNum = curryingAdd(10)(20)
        print(curringNum)
    }
    
    
    //3、柯里化(Currying)加法 三个参数
    do{
        print("-----3-----")
        
        func add(_ num1:Int,_ num2:Int,_ num3:Int) -> Int {num1 + num2 + num3}
        print(add(1, 2, 3))//6
        
        
        //柯里化
        typealias FN = (Int) -> fn
        typealias fn = (Int) -> Int
        func curringAdd(_ num1:Int) -> FN {
            print("num1:",num1)
            
            return { (num2:Int) -> fn in
                print("num1:",num2)
                
                return { (num3:Int) -> Int in
                    print("num3:",num3)
                    
                    return num1 + num2 + num3
                }
            }
        }
        print(curringAdd(1)(2)(3))//6
        
        
        func curringAdd1 (_ num1:Int) -> FN {
             {num2 in
                 {num3 in
                     num1 + num2 + num3
                 }
             }
        }
        print(curringAdd1(1)(2)(3))//6
    }
    
    
    //4、柯里化(Currying)
    do{
        print("-----4-----")
        
        func add(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }
        
        typealias Fiii = (Int,Int) -> Int
        typealias Fif = (Int) -> Fii
        typealias Fii = (Int) -> Int
        func curringAdd (_ fn: @escaping Fiii) -> Fif {
            {a in
                {b in
                    fn(a,b)
                }
            }
        }
        print(curringAdd(add)(10)(20))
    }
    
    //5、柯里化(Currying)4
    do{
        print("-----5-----")
        
        typealias Fabc<A,B,C>   = (A,B)->C
        typealias Fbf<A,B,C>    = (A)->Fbc<B,C>
        typealias Fbc<B,C>      = (B)->(C)
        func currying<A, B, C>(_ fn: @escaping Fabc<A,B,C> ) -> Fbf<A,B,C> {
            { a in
                { b in
                    fn(a, b)
                }
            }
        }
        
        func sum(num1:Int,num2:Int)->Int{num1+num2}
        func sub(num1:Int,num2:Int)->Int{num1-num2}
        func mul(num1:Int,num2:Int)->Int{num1*num2}
        func div(num1:Int,num2:Int)->Int{num1/num2}
        
        
        print(currying(sum)(10)(2)) //12
        print(currying(sub)(10)(2)) //8
        print(currying(mul)(10)(2)) //20
        print(currying(div)(10)(2)) //5
    }
    
    
    
    //6、柯里化(Currying)
    do{
        print("-----6-----")
        
        func sum(num1:Int,num2:Int,num3:Int) -> Int{num1+num2+num3}
        func sub(num1:Int,num2:Int,num3:Int) -> Int{num1-num2-num3}
        
        
        func curringAdd<A,B,C,D>( _ fn: @escaping (A,B,C)->D ) -> (A) -> (B) -> (C) -> D{
            { a in
                { b in
                    { c in
                        fn(a,b,c)
                    }
                }
            }
        }
        
        print(curringAdd(sum)(10)(2)(3))    //15
        print(curringAdd(sub)(10)(2)(3))    //5
    }
    
    //7、获取函数的柯里化版本
    do{
        print("-----7-----")
        
        func sum(num1:Int,num2:Int) -> Int {num1 + num2}
        //获取sum的柯里化版本
        let curringSum = ~sum
        let result = curringSum(10)(2)//12
        print(result)
        print( (~sum)(10)(2) )//12
    
        //获取sub的柯里化版本
        func sub(num1:Int,num2:Int) -> Int {num1 - num2}
        print((~sub)(10)(2))//8
    }
    
    //8、Array、Optional的map方法接收的参数就是一个柯里化函数
    do{
        print("-----8-----")
        
        func doubleFunc(num:Int)->Int{num*2}

        //Array 的 map
        let array = [1,2,3,4]
        print( array.map(doubleFunc) )
        
        //Optional 的 map
        let num : Int? = 10
        print( num.map(doubleFunc) as Any )
    }
}

函子(Functor)

//四、函子(Functor)
infix operator <*> : AdditionPrecedence
func <*><A, B>(fn: ((A) -> B)?, value: A?) -> B? {
    guard let f = fn, let v = value else {
        return nil
    }
    return f(v)
}

func funtionalProgramming4() -> Void {
    
    //1、函子
    do{
        print("-----1-----")
        /**
         像Array、Optional这样支持map运算的类型,称为函子(Functor)
         
         // Array<Element>
         public func map<T>(_ transform: (Element) -> T) -> Array<T>
         
         // Optional<Wrapped>
         public func map<U>(_ transform: (Wrapped) -> U) -> Optional<U>
         */
    }
    
    
    //2、适用函子(Applicative Functor)Optional可以为 适用函子
    do{
        print("-----2-----")
        
        /**
         适用函子(Applicative Functor)
         对任意一个函子 F,如果能支持以下运算,该函子就是一个适用函子
         func pure<A>(_ value: A) -> F<A>
         func <*><A, B>(fn: F<(A) -> B>, value: F<A>) -> F<B>
         */

        //Optional可以成为适用函子
        
        //满足条件一:泛型A可以包装成可选类型
        func pure<A>(_ value: A) -> A? {
            value
        }
        
        //满足条件二:就是将函数fn进行了一次包装
        let value: Int? = 10
        let fn: ((Int) -> Int)? = { $0 * 2}
        // Optional(20)
        print(fn <*> value as Any)
    }
    
    //3、适用函子(Applicative Functor)Array 可以成为适用函子
    do{
        print("-----3-----")
        
        func pure<A>(_ value: A) -> [A] { [value] }
        
        func apfunc<A, B>(_ fn: [(A) -> B], _ value: [A]) -> [B] {
            var arr: [B] = []
            if fn.count == value.count {
                for i in fn.startIndex..<fn.endIndex {
                    arr.append(fn[i](value[i]))
                } }
            return arr
        }
        
        
        print(pure(10))// [10]
        
        
        let arr = apfunc( [{$0 * 2}, {$0 + 10 }, {$0 - 5 }],  [1, 2, 3] )
        print(arr)// [2, 12, -2]
    }
}

单子(Monad)

//五、单子(Monad)
func funtionalProgramming5() -> Void {

    /**
     对任意一个类型 F,如果能支持以下运算,那么就可以称为是一个单子(Monad)
     func pure<A>(_ value: A) -> F<A>
     func flatMap<A, B>(_ value: F<A>,_ fn:(A) -> F<B>) -> F<B>
     很显然,Array、Optional都是单子
     */
    
    //1、Array
    do{
        print("-----1-----")
        
        /**
         func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence
         
         Sequence:NSArray、Array、Dictionary、Set
         
         //简化一下:
         func flatMap(_ transform: (A)  -> [B] ) -> [B]
         
         Array对象调用相当于
         func faltMap(_ value:[A] , _ transform: (A)  -> [B] ) -> [B]
         */
        let arr = [1,2,3,4]
        let newArr = arr.flatMap {[$0*2]}
        print(newArr)
    }
    
    
    
    //2、Optional
    do{
        print("-----2-----")
        
        /**
         @inlinable public func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?
         
         //简化一下
         public func flatMap(_ transform: (A)  -> B?) rethrows -> B?

         Optional调用相当于
         public func flatMap(_ value:A? , _ transform: (A)  -> B?) rethrows -> B?
         */
        let num:Int? = 10
        let newNum = num.flatMap { $0*2 }
        print(newNum as Any)
    }
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.