目录
函数式编程(一)
// 一、函数式编程
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)
}
}
行者常至,为者常成!