魔法师の高塔

Swift函数式编程 4

规范

在前文中,我们应该已经见识了很多类型都会有相似的函数。比如map和flatMap,map函数是把一个普通函数(A->B)作用到一个 F A上,得到一个 F B,flatMap函数是把一个(A -> F B)声明的函数作用到一个F A上,得到一个F B,还有一种是把F (A -> B) 这种函数作用到 F A 上,得到F B。
更规范的描述将会是这样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
public class K0 { public init() {} }
public class K1<A> { public init() {} }
public class K2<A, B> { public init() {} }
typealias AnyThing = protocol <>
protocol Pointed {
associatedtype A
func pure(_ : A) -> Self
}
protocol Functor {
associatedtype A
associatedtype B
associatedtype FB = K1<B>
func fmap(f: A -> B) -> FB
}
protocol Applicative : Pointed,Functor {
associatedtype FAB = K1< A -> B>
func ap(f: FAB) -> FB
}
protocol Monad : Applicative {
func bind(f: A -> FB) -> FB
}
protocol Semigroup {
func op(other : Self) -> Self
}
protocol Monoid : Semigroup {
var mempty : Self {get}
}
indirect enum List<T> {
case Nil
case Cons(T,List<T>)
}
extension List : Semigroup {
func op(other: List) -> List {
return self.append(other)
}
}
extension List : Monoid{
var mempty: List{
return List.Nil
}
}
extension Array{
var list : List<Element>{
if self.isEmpty {
return List.Nil
}else{
let tail = Array(self[1..<self.count])
return List.Cons(self[0], tail.list)
}
}
}
extension List{
var array : [T] {
switch self {
case .Nil:
return []
case .Cons(let head, let tail):
return [head] + tail.array
}
}
func append(l : List<T>) -> List<T> {
switch self {
case .Nil:
return l
case .Cons(let h, let t):
return List<T>.Cons(h, t.append(l))
}
}
func map<B>(f : T -> B) -> List<B> {
switch self {
case .Nil:
return List<B>.Nil
case .Cons(let h, let t):
return List<B>.Cons(f(h), t.map(f))
}
}
func reduce<B>(f : (B, T) -> B, initial : B) -> B {
switch self {
case .Nil:
return initial
case .Cons(let x, let xs):
return xs.reduce(f, initial: f(initial, x))
}
}
func reduce<B>(f : B -> T -> B, initial : B) -> B {
switch self {
case .Nil:
return initial
case .Cons(let x, let xs):
return xs.reduce(f, initial: f(initial)(x))
}
}
}
func concat<A>(xss : List<List<A>>) -> List<A> {
return xss.reduce({ $0.append($1) }, initial: List<A>.Nil)
}
extension List : Pointed{
typealias A = T
func pure(a: A) -> List<A> {
return List<A>.Cons(a, List.Nil)
}
}
extension List : Functor{
typealias B = AnyThing
func fmap(f: A -> B) ->FB {
return self.map(f)
}
}
extension List : Applicative{
typealias FAB = List<A -> B>
typealias FB = List<B>
func ap<B>(f: List<A -> B>) -> List<B> {
return concat(f.map(self.map))
}
}
extension List : Monad{
func bind<B>(f: A -> List<B>) -> List<B> {
switch self {
case .Nil:
return List<B>.Nil
case .Cons(let h, let t):
return f(h).append(t.bind(f))
}
}
}
func friend(name: String)-> List<String>{
if(name == "q"){
return ["qq1","qq2","qq3"].list
}else if(name == "w"){
return ["ww1","ww2","ww3"].list
}else if(name == "e"){
return ["ee1","ee2","ee3","ee4"].list
}else{
return ["rr1","rr2"].list
}
}
let aa = [1,2,3,4,5].list
let pp = [{$0*2},{$0-3},{$0+5}].list
let ap1 = aa.ap(pp).array
print(ap1)
let af = ["q","w","e","r"].list
let am = af.bind(friend).array
print(am)