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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//! Tell combinator - emits a value to be accumulated.
use PhantomData;
use crateWriterEffect;
use crateEffect;
use crateMonoid;
/// An effect that only emits a value, producing unit as output.
///
/// This is the fundamental Writer operation. It produces `()` as output
/// but emits a value that will be accumulated with other writes.
///
/// # Type Parameters
///
/// * `W` - The type to accumulate. Must implement `Monoid`.
/// * `E` - The error type (generic to match chained effects).
/// * `Env` - The environment type (generic to work with any environment).
///
/// # Example
///
/// ```rust
/// use stillwater::effect::writer::prelude::*;
/// use stillwater::effect::prelude::*;
///
/// # tokio_test::block_on(async {
/// let effect = tell::<_, String, ()>(vec!["hello".to_string()]);
/// let (result, writes) = effect.run_writer(&()).await;
///
/// assert_eq!(result, Ok(()));
/// assert_eq!(writes, vec!["hello".to_string()]);
/// # });
/// ```
/// Emit a value to be accumulated.
///
/// Error-generic and environment-generic: works with any `E` and `Env` types.
///
/// # Example
///
/// ```rust
/// use stillwater::effect::writer::prelude::*;
/// use stillwater::effect::prelude::*;
///
/// # tokio_test::block_on(async {
/// // Simple logging - specify error type explicitly
/// let effect = tell::<_, String, ()>(vec!["Starting".to_string()]);
/// let (result, logs) = effect.run_writer(&()).await;
/// assert_eq!(result, Ok(()));
/// assert_eq!(logs, vec!["Starting".to_string()]);
/// # });
/// ```
///
/// # Chaining Writes
///
/// ```rust
/// use stillwater::effect::writer::prelude::*;
/// use stillwater::effect::prelude::*;
///
/// # tokio_test::block_on(async {
/// let effect = tell::<_, String, ()>(vec!["Step 1".to_string()])
/// .and_then(|_| tell(vec!["Step 2".to_string()]));
/// let (result, logs) = effect.run_writer(&()).await;
/// assert_eq!(result, Ok(()));
/// assert_eq!(logs, vec!["Step 1".to_string(), "Step 2".to_string()]);
/// # });
/// ```
///
/// # With Different Monoids
///
/// ```rust
/// use stillwater::effect::writer::prelude::*;
/// use stillwater::effect::prelude::*;
/// use stillwater::monoid::Sum;
///
/// # tokio_test::block_on(async {
/// // Count operations
/// let effect = tell::<_, String, ()>(Sum(1))
/// .and_then(|_| tell(Sum(1)))
/// .and_then(|_| tell(Sum(1)));
/// let (result, Sum(count)) = effect.run_writer(&()).await;
/// assert_eq!(result, Ok(()));
/// assert_eq!(count, 3);
/// # });
/// ```
/// Emit a single item to a Vec accumulator.
///
/// Convenience function for the common case of accumulating items into a Vec.
/// Error-generic and environment-generic: works with any `E` and `Env` types.
///
/// # Example
///
/// ```rust
/// use stillwater::effect::writer::prelude::*;
/// use stillwater::effect::prelude::*;
///
/// # tokio_test::block_on(async {
/// let effect = tell_one::<_, String, ()>("hello".to_string());
/// let (result, writes) = effect.run_writer(&()).await;
///
/// assert_eq!(result, Ok(()));
/// assert_eq!(writes, vec!["hello".to_string()]);
/// # });
/// ```