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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//! Zero-cost Effect trait with opt-in boxing.
//!
//! This module provides a redesigned Effect system that is **zero-cost by default**
//! with **opt-in boxing** when type erasure is needed, following the established
//! `futures` crate pattern.
//!
//! # Getting Started
//!
//! Import the prelude to access free function constructors:
//!
//! ```rust
//! use stillwater::effect::prelude::*;
//!
//! # tokio_test::block_on(async {
//! let effect = pure::<_, String, ()>(42)
//! .map(|x| x * 2);
//!
//! let result = effect.execute(&()).await;
//! assert_eq!(result, Ok(84));
//! # });
//! ```
//!
//! # Free Function Pattern (Recommended)
//!
//! Stillwater provides free functions as the preferred way to create effects:
//!
//! ```rust
//! use stillwater::effect::prelude::*;
//!
//! # tokio_test::block_on(async {
//! // Concise, readable style
//! let effect = asks::<_, String, i32, _>(|env: &i32| env * 2)
//! .and_then(|x| pure(x + 1));
//!
//! let result = effect.execute(&42).await;
//! assert_eq!(result, Ok(85));
//! # });
//! ```
//!
//! See [`constructors`] module for the complete list of free functions.
//!
//! # Key Differences from Old API
//!
//! | Old API | New API |
//! |---------|---------|
//! | `Effect<T, E, Env>` struct (boxed per combinator) | `impl Effect<Output=T, Error=E, Env=Env>` (zero-cost) |
//! | `Effect::pure(x)` | `pure::<_, E, Env>(x)` |
//! | `Effect::fail(e)` | `fail::<T, _, Env>(e)` |
//! | Automatic type erasure | Explicit `.boxed()` when needed |
//!
//! # Zero-Cost by Default
//!
//! ```rust,ignore
//! use stillwater::effect::prelude::*;
//!
//! // Zero heap allocations - compiler can inline everything
//! let effect = pure::<_, String, ()>(42)
//! .map(|x| x + 1) // Returns Map<Pure<...>, ...>
//! .and_then(|x| pure(x * 2)) // Returns AndThen<Map<...>, ...>
//! .map(|x| x.to_string()); // Returns Map<AndThen<...>, ...>
//!
//! // Type: Map<AndThen<Map<Pure<i32, String, ()>, ...>, ...>, ...>
//! // NO heap allocation!
//! ```
//!
//! # When to Use Boxing
//!
//! Boxing is needed in exactly three cases:
//!
//! ## 1. Storing in Collections
//!
//! ```rust,ignore
//! // Can't put different types in a Vec!
//! let effects: Vec<BoxedEffect<i32, E, Env>> = vec![
//! pure(1).boxed(),
//! pure(2).map(|x| x * 2).boxed(),
//! ];
//! ```
//!
//! ## 2. Recursive Effects
//!
//! ```rust,ignore
//! fn countdown(n: i32) -> BoxedEffect<i32, String, ()> {
//! if n <= 0 {
//! pure(0).boxed()
//! } else {
//! pure(n)
//! .and_then(move |x| countdown(x - 1).map(move |sum| x + sum))
//! .boxed()
//! }
//! }
//! ```
//!
//! ## 3. Match Arms with Different Effect Types
//!
//! ```rust,ignore
//! fn get_user(source: DataSource) -> BoxedEffect<User, E, Env> {
//! match source {
//! DataSource::Cache => pure(user).boxed(),
//! DataSource::Database => fetch_from_db().boxed(),
//! }
//! }
//! ```
//!
//! # Environment Cloning
//!
//! The environment (`Env`) must implement `Clone`. This is required for boxing,
//! where the environment is cloned into the boxed future to achieve `'static`
//! lifetime. This is typically cheap when environments contain `Arc`-wrapped
//! resources:
//!
//! ```rust,ignore
//! #[derive(Clone)]
//! struct AppEnv {
//! db: Arc<DatabasePool>, // Clone is cheap (Arc refcount)
//! config: Arc<Config>,
//! http: Arc<HttpClient>,
//! }
//! ```
// Re-export core trait
pub use Effect;
// Re-export extension trait
pub use EffectExt;
// Re-export boxed types
pub use ;
// Re-export all combinator types
pub use ;
// Re-export reader types
pub use ;
// Re-export bracket
pub use bracket_simple;
pub use ;
// Re-export constructors
pub use ;
// Re-export parallel functions
pub use ;
// Re-export context trait
pub use ;
// Re-export retry functions (when async feature is enabled)
pub use ;
// Re-export tracing (when tracing feature is enabled)
pub use ;
// Re-export compatibility items
pub use ;