-
Notifications
You must be signed in to change notification settings - Fork 52
/
Func.swift
123 lines (98 loc) · 2.86 KB
/
Func.swift
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
public struct Func<A, B> {
public let call: (A) -> B
public init(_ call: @escaping (A) -> B) {
self.call = call
}
}
extension Func /* : Semigroupoid */ {
public static func >>> <C>(f: Func, g: Func<B, C>) -> Func<A, C> {
return .init(f.call >>> g.call)
}
public static func <<< <C>(f: Func<B, C>, g: Func) -> Func<A, C> {
return .init(f.call <<< g.call)
}
}
extension Func /* : Functor */ {
public func map<C>(_ f: @escaping (B) -> C) -> Func<A, C> {
return .init(self.call >>> f)
}
public static func <¢> <C>(f: @escaping (B) -> C, g: Func) -> Func<A, C> {
return g.map(f)
}
}
public func map<A, B, C>(_ f: @escaping (B) -> C) -> (Func<A, B>) -> Func<A, C> {
return { $0.map(f) }
}
extension Func /* : Contravariant */ {
public func contramap<Z>(_ f: @escaping (Z) -> A) -> Func<Z, B> {
return .init(f >>> self.call)
}
public static func >¢< <A, B, C>(f: @escaping (B) -> A, g: Func<A, C>) -> Func<B, C> {
return g.contramap(f)
}
}
public func contramap<A, B, C>(_ f: @escaping (B) -> A) -> (Func<A, C>) -> Func<B, C> {
return { $0.contramap(f) }
}
extension Func /* : Profunctor */ {
public func dimap<Z, C>(_ f: @escaping (Z) -> A, _ g: @escaping (B) -> C) -> Func<Z, C> {
return .init(f >>> self.call >>> g)
}
}
public func dimap<A, B, C, D>(
_ f: @escaping (A) -> B,
_ g: @escaping (C) -> D
)
-> (Func<B, C>)
-> Func<A, D> {
return { $0.dimap(f, g) }
}
extension Func /* : Apply */ {
public func apply<C>(_ f: Func<A, Func<B, C>>) -> Func<A, C> {
return .init { a in f.call(a).call(self.call(a)) }
}
public static func <*> <C>(f: Func<A, Func<B, C>>, x: Func) -> Func<A, C> {
return x.apply(f)
}
}
public func apply<A, B, C>(_ f: Func<A, Func<B, C>>) -> (Func<A, B>) -> Func<A, C> {
return { $0.apply(f) }
}
// MARK: Applicative
public func pure<A, B>(_ b: B) -> Func<A, B> {
return .init(const(b))
}
extension Func /* : Monad */ {
public func flatMap<C>(_ f: @escaping (B) -> Func<A, C>) -> Func<A, C> {
return .init { f(self.call($0)).call($0) }
}
}
public func flatMap<A, B, C>(_ f: @escaping (B) -> Func<A, C>) -> (Func<A, B>) -> Func<A, C> {
return { $0.flatMap(f) }
}
extension Func: Semigroup where B: Semigroup {
public static func <> (f: Func, g: Func) -> Func {
return .init { f.call($0) <> g.call($0) }
}
}
extension Func: Monoid where B: Monoid {
public static var empty: Func {
return .init(const(B.empty))
}
}
extension Func: NearSemiring where B: NearSemiring {
public static func + (f: Func, g: Func) -> Func {
return .init { f.call($0) + g.call($0) }
}
public static func * (f: Func, g: Func) -> Func {
return .init { f.call($0) * g.call($0) }
}
public static var zero: Func {
return .init(const(B.zero))
}
}
extension Func: Semiring where B: Semiring {
public static var one: Func {
return .init(const(B.one))
}
}