1
|
|
import Foundation
|
2
|
|
|
3
|
|
/// A Comonad is the dual of a `Monad`. It provides capabilities to compose functions that extract values from their context.
|
4
|
|
///
|
5
|
|
/// Implementations of this instance must obey the following laws:
|
6
|
|
///
|
7
|
|
/// extract(duplicate(fa)) == fa
|
8
|
|
/// map(fa, f) == coflatMap(fa, { a in f(extract(a)) }
|
9
|
|
/// coflatMap(fa, extract) == fa
|
10
|
|
/// extract(coflatMap(fa, f)) == f(fa)
|
11
|
|
///
|
12
|
|
public protocol Comonad: Functor {
|
13
|
|
/// Applies a value in the context implementing this instance to a function that takes a value in a context, and returns a normal value.
|
14
|
|
///
|
15
|
|
/// This function is the dual of `Monad.flatMap`.
|
16
|
|
///
|
17
|
|
/// - Parameters:
|
18
|
|
/// - fa: Value in the context implementing this instance.
|
19
|
|
/// - f: Extracting function.
|
20
|
|
/// - Returns: The result of extracting and transforming the value, in the context implementing this instance.
|
21
|
|
static func coflatMap<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (Kind<Self, A>) -> B) -> Kind<Self, B>
|
22
|
|
|
23
|
|
/// Extracts the value contained in the context implementing this instance.
|
24
|
|
///
|
25
|
|
/// This function is the dual of `Monad.pure` (via `Applicative`).
|
26
|
|
///
|
27
|
|
/// - Parameter fa: A value in the context implementing this instance.
|
28
|
|
/// - Returns: A normal value.
|
29
|
|
static func extract<A>(_ fa: Kind<Self, A>) -> A
|
30
|
|
}
|
31
|
|
|
32
|
|
// MARK: Related functions
|
33
|
|
|
34
|
|
public extension Comonad {
|
35
|
|
/// Wraps a value in another layer of the context implementing this instance.
|
36
|
|
///
|
37
|
|
/// - Parameter fa: A value in the context implementing this instance.
|
38
|
|
/// - Returns: Value wrapped in another context layer.
|
39
|
1
|
static func duplicate<A>(_ fa: Kind<Self, A>) -> Kind<Self, Kind<Self, A>> {
|
40
|
1
|
return coflatMap(fa, id)
|
41
|
|
}
|
42
|
|
}
|
43
|
|
|
44
|
|
// MARK: Syntax for Comonad
|
45
|
|
|
46
|
|
public extension Kind where F: Comonad {
|
47
|
|
/// Applies this value to a function that takes a value in this context, and returns a normal value.
|
48
|
|
///
|
49
|
|
/// This function is the dual of `Monad.flatMap`.
|
50
|
|
///
|
51
|
|
/// This is a convenience function to call `Comonad.coflatMap` as an instance method.
|
52
|
|
///
|
53
|
|
/// - Parameters:
|
54
|
|
/// - f: Extracting function.
|
55
|
|
/// - Returns: The result of extracting and transforming the value, in the context implementing this instance.
|
56
|
1
|
func coflatMap<B>(_ f: @escaping (Kind<F, A>) -> B) -> Kind<F, B> {
|
57
|
1
|
return F.coflatMap(self, f)
|
58
|
|
}
|
59
|
|
|
60
|
|
/// Extracts the value contained in this context.
|
61
|
|
///
|
62
|
|
/// This function is the dual of `Monad.pure` (via `Applicative`).
|
63
|
|
///
|
64
|
|
/// This is a convenience function to call `Comonad.extract` as an instance method.
|
65
|
|
///
|
66
|
|
/// - Returns: A normal value.
|
67
|
1
|
func extract() -> A {
|
68
|
1
|
return F.extract(self)
|
69
|
|
}
|
70
|
|
|
71
|
|
/// Wraps this in another layer of this context.
|
72
|
|
///
|
73
|
|
/// - Returns: This value wrapped in another context layer.
|
74
|
0
|
func duplicate() -> Kind<F, Kind<F, A>> {
|
75
|
0
|
return F.duplicate(self)
|
76
|
|
}
|
77
|
|
}
|