函数式编程(Funtional Programming,简称FP)是一种编程范式,也就是如何编写程序的方法论
主要思想:把计算过程尽量分解成一系列可复用函数的调用 主要特征:函数是“第一等公民”: 函数与其他数据类型一样的地位,可以赋值给其他变量,也可以作为函数参数、函数返回值
函数式编程最早出现在LISP语言,绝大大部分的代码编程语言也对函数式编程做了不同程度的支持,比如:Haskell、JavaScript、Python、Swift、Kotlin、Scala等 函数时编程中的几个常用的概念
Higher-Order Function、Function Currying Functor、Applicatie Functor、Monad
参考资料: http://www.mokacoding.com/blog/functor-applicative-monads-in-pictures/
FP实践 - 传统写法
let num = 1
func add ( _ v1: Int , _ v2: Int ) - > Int { v1 + v2 }
func sub ( _ v1: Int , _ v2: Int ) - > Int { v1 - v2 }
func multiple ( _ v1: Int , _ v2: Int ) - > Int { v1 * v2 }
func divide ( _ v1: Int , _ v2: Int ) - > Int { v1 / v2 }
func mod ( _ v1: Int , _ v2: Int ) - > Int { v1 % v2 }
let result = divide ( mod ( sub ( multiple ( add ( num, 3 ) , 5 ) , 1 ) , 10 ) , 2 )
print ( result)
FP实践 - 函数式写法
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 } }
func composite ( _ f1: @escaping ( Int ) - > Int ,
_ f2: @escaping ( Int ) - > Int ) - > ( Int ) - > Int {
return { f2 ( f1 ( $0 ) ) }
}
let fn = composite ( add ( 3 ) , multiple ( 5 ) )
print ( fn ( num) )
infix operator > > > : AdditoinPrecedence
func > > > ( _ f1: @escaping ( Int ) - > Int ,
_ f2: @escaping ( Int ) - > Int ) - > ( Int ) - > Int { return { f2 ( f1 ( $0 ) ) } }
let fn = add ( 3 ) > > > multiple ( 5 )
print ( fn ( num) )
函数合成 - 利用符号 - 泛型
infix operator > > > : AdditoinPrecedence
func > > > < A, B, C> ( _ f1: @escaping ( A) - > B,
_ f2: @escaping ( B) - > C) - > ( A) - > C { return { f2 ( f1 ( $0 ) ) } }
let fn = add ( 3 ) > > > multiple ( 5 )
print ( fn ( num) )
let fn = add ( 3 ) > > > multiple ( 5 ) > > > sub ( 1 ) > > > mod ( 10 ) > > > divide ( 2 )
print ( fn ( num) )
高阶函数(Higher-Order Function)
接受一个或多个函数作为输入(map、filter、reduce等) 返回一个函数
柯里化(Currying)
将一个接受多参数的函数变换为一系列只接受单个参数的函数
func add1 ( _ v1: Int , _ v2: Int ) - > Int { v1 + v2 }
add1 ( 10 , 20 )
func add1 ( _ v: Int ) - > ( Int ) - > Int { { $0 + v } }
add1 ( 10 ) ( 20 )
Array、Optional的map方法接受的参数就是一个柯里化函数 三个参数柯里化
func add2 ( _ v1: Int , _ v2: Int , v3: Int ) - > Int { v1 + v2 + v3 }
func add2 ( _ v3: Int ) - > ( Int ) - > ( Int ) - > Int {
return { v2 in
return { v1 in
return v1 + v2 + v3
}
}
}
add2 ( 10 , 20 , 30 )
add2 ( 30 ) ( 20 ) ( 10 )
func currying< A, B, C> ( _ fn: @escaping ( A, B) - > C) - > ( B) - > ( A) - > C {
return { b in
return { a in
return fn ( a, b)
}
}
}
currying ( add1 ( 20 ) ( 10 ) )
prefix func ~ < A, B, C> ( _ fn: @escaping ( A, B) - > C)
- > ( B) - > ( A) - > C {
{ b in { a in fn ( a, b) } }
}
print ( ( ~ sub ( 20 ) ( 10 ) )
let fn = ( ~ add) ( 3 ) > > > ( ~ multiple) ( 5 ) > > > ( ~ sub) ( 1 ) > > > ( ~ mod) ( 10 ) > > > ( ~ divide) ( 2 )
print ( fn ( 1 ) )
prefix func ~ < A, B, C, D> ( _ fn: @escaping ( A, B, C) - > D)
- > ( C) - > ( B) - > ( A) - > D {
{ c in { b in { a in fn ( a, b, c) } } }
}
print ( ( ~ add2) ( 30 ) ( 20 ) ( 10 ) )
函子(Functor)
像Array、Optional这样支持map运算的类型,成为函子(Functor) 怎么样的Type才能称之为函子呢?
func map < T> ( _ fn: ( Inner ) - > T) - > Type < T>
func map < T> ( _ fn: ( Element ) - > T) - > Array < T>
func map < T> ( _ fn: ( Wrapped ) - > T) - > Opional < T>
适用函子(Applicative Functor)
对任意一个函子F,如果能支持一下运算,该函子就是一个适用函子
func pure< A> ( _ value: A) - > F< A>
func < * > < A, B> ( fn: F< ( A) - > B> , value: F< A> ) - > F< B>
func pure< A> ( _ value: A) - > A? { value }
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)
}
var value: Int? = 10
var fn: ((Int) -> Int)? = { $0 * 2 }
// Optional
print(fn <*> value as Any)
func pure< A> ( _ value: A) - > [ A] { [ value] }
func < * > < 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 ) )
var arr = [ { $0 * 2 } , { $0 + 10 } , { $0 - 5 } ] < * > [ 1 , 2 , 3 ]
print ( arr)
单子(Monad)
对于任意一个类型F,如果能支持一下运算,那么就可以成为是一个单子(Monad)
func pure< A> ( _ value: A) - > F< A>
func flatMap< A, B> ( _ value: F< A> , _ fn: ( A) - > F< B> ) - > F< B>