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
}

Read our documentation on viewing source code .

Loading