pub struct Prism<S, T, A, B> { /* private fields */ }Expand description
A prism focuses on one variant of a sum type.
S — source type, T — modified source type,
A — focus type (the variant’s inner value), B — replacement type.
Where a Lens uses Strong to
decompose products, a Prism uses Choice to decompose coproducts.
For simple (monomorphic) prisms, use SimplePrism.
Implementations§
Source§impl<S, T, A, B> Prism<S, T, A, B>
impl<S, T, A, B> Prism<S, T, A, B>
Sourcepub fn new(
match_: fn(S) -> Result<A, T>,
build: fn(B) -> T,
) -> Prism<S, T, A, B>
pub fn new( match_: fn(S) -> Result<A, T>, build: fn(B) -> T, ) -> Prism<S, T, A, B>
Examples found in repository?
91fn credit_card_prism() -> SimplePrism<Payment, (String, String)> {
92 Prism::new(
93 |p| match p {
94 Payment::CreditCard { last4, exp } => Ok((last4, exp)),
95 other => Err(other),
96 },
97 |(last4, exp)| Payment::CreditCard { last4, exp },
98 )
99}
100
101fn wallet_prism() -> SimplePrism<Payment, (String, i64)> {
102 Prism::new(
103 |p| match p {
104 Payment::Wallet {
105 provider,
106 balance_cents,
107 } => Ok((provider, balance_cents)),
108 other => Err(other),
109 },
110 |(provider, balance_cents)| Payment::Wallet {
111 provider,
112 balance_cents,
113 },
114 )
115}
116
117fn bank_transfer_prism() -> SimplePrism<Payment, String> {
118 Prism::new(
119 |p| match p {
120 Payment::BankTransfer { iban } => Ok(iban),
121 other => Err(other),
122 },
123 |iban| Payment::BankTransfer { iban },
124 )
125}Sourcepub fn preview(&self, s: &S) -> Option<A>where
S: Clone,
pub fn preview(&self, s: &S) -> Option<A>where
S: Clone,
Try to extract the focus. Returns Some(a) if the variant matches.
Examples found in repository?
159fn main() {
160 println!("=== Domain Model with Optics Example ===\n");
161
162 let order = sample_order();
163
164 // 1. Lens: get/set/over
165 println!("--- Lens: basic get/set/over ---");
166 let customer = customer_lens();
167 let address = address_lens();
168 let city = city_lens();
169
170 println!(" Customer name: {}", name_lens().get(&order.customer));
171 println!(" City: {}", city.get(&address.get(&customer.get(&order))));
172
173 // 2. Composed Lens: deep access with .then()
174 println!("\n--- ComposedLens: deep access with .then() ---");
175 let order_city = customer_lens().then(address_lens()).then(city_lens());
176 let order_zip = customer_lens().then(address_lens()).then(zip_lens());
177
178 println!(" Order city: {}", order_city.get(&order));
179 println!(" Order zip: {}", order_zip.get(&order));
180
181 // Deep set
182 let updated = order_city.set(order.clone(), "Shelbyville".into());
183 println!(" After city update: {}", order_city.get(&updated));
184 println!(" Original unchanged: {}", order_city.get(&order));
185
186 // Deep over (modify)
187 let uppercased = order_city.over(order.clone(), |c| c.to_uppercase());
188 println!(" Uppercased city: {}", order_city.get(&uppercased));
189
190 // 3. Lens::transform — reusable update function
191 println!("\n--- Lens::transform — reusable update function ---");
192 let normalize_city: Box<dyn Fn(String) -> String> = Box::new(|c| c.trim().to_uppercase());
193 let normalize_order_city = city_lens().transform::<FnP>(normalize_city);
194 let addr = Address {
195 street: "456 Oak Ave".into(),
196 city: " new york ".into(),
197 zip: "10001".into(),
198 };
199 let normalized = normalize_order_city(addr);
200 println!(" Normalized city: {:?}", normalized.city);
201
202 // 4. Prism: sum type focus
203 println!("\n--- Prism: sum type focus ---");
204 let cc = credit_card_prism();
205 let wallet = wallet_prism();
206 let bank = bank_transfer_prism();
207
208 println!(" Credit card last4: {:?}", cc.preview(&order.payment));
209 println!(" Wallet preview: {:?}", wallet.preview(&order.payment));
210
211 // Prism::review — construct a variant
212 let new_payment = wallet.review(("PayPal".into(), 5000));
213 println!(" New wallet payment: {:?}", new_payment);
214
215 // Prism::over — modify only if matched
216 let updated_payment = cc.over(order.payment.clone(), |(last4, _exp)| {
217 (last4, "01/28".into())
218 });
219 println!(" Updated CC expiry: {:?}", updated_payment);
220
221 // Prism on non-matching variant: passes through unchanged
222 let unchanged = wallet.over(order.payment.clone(), |(prov, bal)| (prov, bal + 1000));
223 println!(" Wallet over on CC (unchanged): {:?}", unchanged);
224
225 // 5. Prism::transform — reusable pattern-matching function
226 println!("\n--- Prism::transform — reusable variant modifier ---");
227 let add_balance: Box<dyn Fn((String, i64)) -> (String, i64)> =
228 Box::new(|(prov, bal)| (prov, bal + 2500));
229 let add_wallet_balance = wallet.transform::<FnP>(add_balance);
230
231 let wallet_payment = Payment::Wallet {
232 provider: "PayPal".into(),
233 balance_cents: 10000,
234 };
235 let topped_up = add_wallet_balance(wallet_payment);
236 println!(" Topped up: {:?}", topped_up);
237
238 // Apply same transform to non-wallet — passes through
239 let still_cc = add_wallet_balance(order.payment.clone());
240 println!(" CC unchanged: {:?}", still_cc);
241
242 // 6. Summary: combine multiple optics
243 println!("\n--- Combining lenses and prisms ---");
244 let orders = vec![
245 sample_order(),
246 Order {
247 id: 1002,
248 customer: Customer {
249 name: "Bob Jones".into(),
250 address: Address {
251 street: "789 Elm St".into(),
252 city: "Capital City".into(),
253 zip: "12345".into(),
254 },
255 },
256 items: vec![Item {
257 name: "Mouse".into(),
258 price_cents: 2999,
259 quantity: 1,
260 }],
261 payment: Payment::Wallet {
262 provider: "Stripe".into(),
263 balance_cents: 50000,
264 },
265 },
266 Order {
267 id: 1003,
268 customer: Customer {
269 name: "Carol White".into(),
270 address: Address {
271 street: "321 Pine Rd".into(),
272 city: "Springfield".into(),
273 zip: "62702".into(),
274 },
275 },
276 items: vec![],
277 payment: Payment::BankTransfer {
278 iban: "DE89370400440532013000".into(),
279 },
280 },
281 ];
282
283 let order_city_lens = customer_lens().then(address_lens()).then(city_lens());
284 println!(" All cities:");
285 for o in &orders {
286 let payment_type = match &o.payment {
287 Payment::CreditCard { .. } => "CC",
288 Payment::BankTransfer { .. } => "Bank",
289 Payment::Wallet { .. } => "Wallet",
290 };
291 println!(
292 " Order #{}: {} ({}, pays via {})",
293 o.id,
294 order_city_lens.get(o),
295 name_lens().get(&o.customer),
296 payment_type
297 );
298 }
299
300 // Find all bank IBANs using Prism
301 println!("\n Bank IBANs:");
302 for o in &orders {
303 if let Some(iban) = bank.preview(&o.payment) {
304 println!(" Order #{}: {}", o.id, iban);
305 }
306 }
307}Sourcepub fn review(&self, b: B) -> T
pub fn review(&self, b: B) -> T
Construct a T from a replacement value (inject/construct).
Examples found in repository?
159fn main() {
160 println!("=== Domain Model with Optics Example ===\n");
161
162 let order = sample_order();
163
164 // 1. Lens: get/set/over
165 println!("--- Lens: basic get/set/over ---");
166 let customer = customer_lens();
167 let address = address_lens();
168 let city = city_lens();
169
170 println!(" Customer name: {}", name_lens().get(&order.customer));
171 println!(" City: {}", city.get(&address.get(&customer.get(&order))));
172
173 // 2. Composed Lens: deep access with .then()
174 println!("\n--- ComposedLens: deep access with .then() ---");
175 let order_city = customer_lens().then(address_lens()).then(city_lens());
176 let order_zip = customer_lens().then(address_lens()).then(zip_lens());
177
178 println!(" Order city: {}", order_city.get(&order));
179 println!(" Order zip: {}", order_zip.get(&order));
180
181 // Deep set
182 let updated = order_city.set(order.clone(), "Shelbyville".into());
183 println!(" After city update: {}", order_city.get(&updated));
184 println!(" Original unchanged: {}", order_city.get(&order));
185
186 // Deep over (modify)
187 let uppercased = order_city.over(order.clone(), |c| c.to_uppercase());
188 println!(" Uppercased city: {}", order_city.get(&uppercased));
189
190 // 3. Lens::transform — reusable update function
191 println!("\n--- Lens::transform — reusable update function ---");
192 let normalize_city: Box<dyn Fn(String) -> String> = Box::new(|c| c.trim().to_uppercase());
193 let normalize_order_city = city_lens().transform::<FnP>(normalize_city);
194 let addr = Address {
195 street: "456 Oak Ave".into(),
196 city: " new york ".into(),
197 zip: "10001".into(),
198 };
199 let normalized = normalize_order_city(addr);
200 println!(" Normalized city: {:?}", normalized.city);
201
202 // 4. Prism: sum type focus
203 println!("\n--- Prism: sum type focus ---");
204 let cc = credit_card_prism();
205 let wallet = wallet_prism();
206 let bank = bank_transfer_prism();
207
208 println!(" Credit card last4: {:?}", cc.preview(&order.payment));
209 println!(" Wallet preview: {:?}", wallet.preview(&order.payment));
210
211 // Prism::review — construct a variant
212 let new_payment = wallet.review(("PayPal".into(), 5000));
213 println!(" New wallet payment: {:?}", new_payment);
214
215 // Prism::over — modify only if matched
216 let updated_payment = cc.over(order.payment.clone(), |(last4, _exp)| {
217 (last4, "01/28".into())
218 });
219 println!(" Updated CC expiry: {:?}", updated_payment);
220
221 // Prism on non-matching variant: passes through unchanged
222 let unchanged = wallet.over(order.payment.clone(), |(prov, bal)| (prov, bal + 1000));
223 println!(" Wallet over on CC (unchanged): {:?}", unchanged);
224
225 // 5. Prism::transform — reusable pattern-matching function
226 println!("\n--- Prism::transform — reusable variant modifier ---");
227 let add_balance: Box<dyn Fn((String, i64)) -> (String, i64)> =
228 Box::new(|(prov, bal)| (prov, bal + 2500));
229 let add_wallet_balance = wallet.transform::<FnP>(add_balance);
230
231 let wallet_payment = Payment::Wallet {
232 provider: "PayPal".into(),
233 balance_cents: 10000,
234 };
235 let topped_up = add_wallet_balance(wallet_payment);
236 println!(" Topped up: {:?}", topped_up);
237
238 // Apply same transform to non-wallet — passes through
239 let still_cc = add_wallet_balance(order.payment.clone());
240 println!(" CC unchanged: {:?}", still_cc);
241
242 // 6. Summary: combine multiple optics
243 println!("\n--- Combining lenses and prisms ---");
244 let orders = vec![
245 sample_order(),
246 Order {
247 id: 1002,
248 customer: Customer {
249 name: "Bob Jones".into(),
250 address: Address {
251 street: "789 Elm St".into(),
252 city: "Capital City".into(),
253 zip: "12345".into(),
254 },
255 },
256 items: vec![Item {
257 name: "Mouse".into(),
258 price_cents: 2999,
259 quantity: 1,
260 }],
261 payment: Payment::Wallet {
262 provider: "Stripe".into(),
263 balance_cents: 50000,
264 },
265 },
266 Order {
267 id: 1003,
268 customer: Customer {
269 name: "Carol White".into(),
270 address: Address {
271 street: "321 Pine Rd".into(),
272 city: "Springfield".into(),
273 zip: "62702".into(),
274 },
275 },
276 items: vec![],
277 payment: Payment::BankTransfer {
278 iban: "DE89370400440532013000".into(),
279 },
280 },
281 ];
282
283 let order_city_lens = customer_lens().then(address_lens()).then(city_lens());
284 println!(" All cities:");
285 for o in &orders {
286 let payment_type = match &o.payment {
287 Payment::CreditCard { .. } => "CC",
288 Payment::BankTransfer { .. } => "Bank",
289 Payment::Wallet { .. } => "Wallet",
290 };
291 println!(
292 " Order #{}: {} ({}, pays via {})",
293 o.id,
294 order_city_lens.get(o),
295 name_lens().get(&o.customer),
296 payment_type
297 );
298 }
299
300 // Find all bank IBANs using Prism
301 println!("\n Bank IBANs:");
302 for o in &orders {
303 if let Some(iban) = bank.preview(&o.payment) {
304 println!(" Order #{}: {}", o.id, iban);
305 }
306 }
307}Sourcepub fn set(&self, s: S, b: B) -> T
pub fn set(&self, s: S, b: B) -> T
Replace the focus if the variant matches; otherwise pass through.
Sourcepub fn over(&self, s: S, f: impl FnOnce(A) -> B) -> T
pub fn over(&self, s: S, f: impl FnOnce(A) -> B) -> T
Modify the focus if the variant matches; otherwise pass through.
Examples found in repository?
159fn main() {
160 println!("=== Domain Model with Optics Example ===\n");
161
162 let order = sample_order();
163
164 // 1. Lens: get/set/over
165 println!("--- Lens: basic get/set/over ---");
166 let customer = customer_lens();
167 let address = address_lens();
168 let city = city_lens();
169
170 println!(" Customer name: {}", name_lens().get(&order.customer));
171 println!(" City: {}", city.get(&address.get(&customer.get(&order))));
172
173 // 2. Composed Lens: deep access with .then()
174 println!("\n--- ComposedLens: deep access with .then() ---");
175 let order_city = customer_lens().then(address_lens()).then(city_lens());
176 let order_zip = customer_lens().then(address_lens()).then(zip_lens());
177
178 println!(" Order city: {}", order_city.get(&order));
179 println!(" Order zip: {}", order_zip.get(&order));
180
181 // Deep set
182 let updated = order_city.set(order.clone(), "Shelbyville".into());
183 println!(" After city update: {}", order_city.get(&updated));
184 println!(" Original unchanged: {}", order_city.get(&order));
185
186 // Deep over (modify)
187 let uppercased = order_city.over(order.clone(), |c| c.to_uppercase());
188 println!(" Uppercased city: {}", order_city.get(&uppercased));
189
190 // 3. Lens::transform — reusable update function
191 println!("\n--- Lens::transform — reusable update function ---");
192 let normalize_city: Box<dyn Fn(String) -> String> = Box::new(|c| c.trim().to_uppercase());
193 let normalize_order_city = city_lens().transform::<FnP>(normalize_city);
194 let addr = Address {
195 street: "456 Oak Ave".into(),
196 city: " new york ".into(),
197 zip: "10001".into(),
198 };
199 let normalized = normalize_order_city(addr);
200 println!(" Normalized city: {:?}", normalized.city);
201
202 // 4. Prism: sum type focus
203 println!("\n--- Prism: sum type focus ---");
204 let cc = credit_card_prism();
205 let wallet = wallet_prism();
206 let bank = bank_transfer_prism();
207
208 println!(" Credit card last4: {:?}", cc.preview(&order.payment));
209 println!(" Wallet preview: {:?}", wallet.preview(&order.payment));
210
211 // Prism::review — construct a variant
212 let new_payment = wallet.review(("PayPal".into(), 5000));
213 println!(" New wallet payment: {:?}", new_payment);
214
215 // Prism::over — modify only if matched
216 let updated_payment = cc.over(order.payment.clone(), |(last4, _exp)| {
217 (last4, "01/28".into())
218 });
219 println!(" Updated CC expiry: {:?}", updated_payment);
220
221 // Prism on non-matching variant: passes through unchanged
222 let unchanged = wallet.over(order.payment.clone(), |(prov, bal)| (prov, bal + 1000));
223 println!(" Wallet over on CC (unchanged): {:?}", unchanged);
224
225 // 5. Prism::transform — reusable pattern-matching function
226 println!("\n--- Prism::transform — reusable variant modifier ---");
227 let add_balance: Box<dyn Fn((String, i64)) -> (String, i64)> =
228 Box::new(|(prov, bal)| (prov, bal + 2500));
229 let add_wallet_balance = wallet.transform::<FnP>(add_balance);
230
231 let wallet_payment = Payment::Wallet {
232 provider: "PayPal".into(),
233 balance_cents: 10000,
234 };
235 let topped_up = add_wallet_balance(wallet_payment);
236 println!(" Topped up: {:?}", topped_up);
237
238 // Apply same transform to non-wallet — passes through
239 let still_cc = add_wallet_balance(order.payment.clone());
240 println!(" CC unchanged: {:?}", still_cc);
241
242 // 6. Summary: combine multiple optics
243 println!("\n--- Combining lenses and prisms ---");
244 let orders = vec![
245 sample_order(),
246 Order {
247 id: 1002,
248 customer: Customer {
249 name: "Bob Jones".into(),
250 address: Address {
251 street: "789 Elm St".into(),
252 city: "Capital City".into(),
253 zip: "12345".into(),
254 },
255 },
256 items: vec![Item {
257 name: "Mouse".into(),
258 price_cents: 2999,
259 quantity: 1,
260 }],
261 payment: Payment::Wallet {
262 provider: "Stripe".into(),
263 balance_cents: 50000,
264 },
265 },
266 Order {
267 id: 1003,
268 customer: Customer {
269 name: "Carol White".into(),
270 address: Address {
271 street: "321 Pine Rd".into(),
272 city: "Springfield".into(),
273 zip: "62702".into(),
274 },
275 },
276 items: vec![],
277 payment: Payment::BankTransfer {
278 iban: "DE89370400440532013000".into(),
279 },
280 },
281 ];
282
283 let order_city_lens = customer_lens().then(address_lens()).then(city_lens());
284 println!(" All cities:");
285 for o in &orders {
286 let payment_type = match &o.payment {
287 Payment::CreditCard { .. } => "CC",
288 Payment::BankTransfer { .. } => "Bank",
289 Payment::Wallet { .. } => "Wallet",
290 };
291 println!(
292 " Order #{}: {} ({}, pays via {})",
293 o.id,
294 order_city_lens.get(o),
295 name_lens().get(&o.customer),
296 payment_type
297 );
298 }
299
300 // Find all bank IBANs using Prism
301 println!("\n Bank IBANs:");
302 for o in &orders {
303 if let Some(iban) = bank.preview(&o.payment) {
304 println!(" Order #{}: {}", o.id, iban);
305 }
306 }
307}Sourcepub fn to_setter(&self) -> Setter<S, T, A, B>where
S: 'static,
T: 'static,
A: 'static,
B: 'static,
pub fn to_setter(&self) -> Setter<S, T, A, B>where
S: 'static,
T: 'static,
A: 'static,
B: 'static,
Convert to a Setter (modify-only).
Sourcepub fn to_traversal(&self) -> Traversal<S, T, A, B>where
S: Clone + 'static,
T: 'static,
A: 'static,
B: 'static,
pub fn to_traversal(&self) -> Traversal<S, T, A, B>where
S: Clone + 'static,
T: 'static,
A: 'static,
B: 'static,
Convert to a Traversal (0-or-1 element focus).
Sourcepub fn to_fold(&self) -> Fold<S, A>where
S: Clone + 'static,
T: 'static,
A: 'static,
pub fn to_fold(&self) -> Fold<S, A>where
S: Clone + 'static,
T: 'static,
A: 'static,
Convert to a Fold (0-or-1 element, read-only).
Sourcepub fn transform<P>(&self, pab: <P as HKT2>::P<A, B>) -> <P as HKT2>::P<S, T>where
P: Choice,
S: 'static,
T: 'static,
A: 'static,
B: 'static,
pub fn transform<P>(&self, pab: <P as HKT2>::P<A, B>) -> <P as HKT2>::P<S, T>where
P: Choice,
S: 'static,
T: 'static,
A: 'static,
B: 'static,
Profunctor encoding: transform a P<A, B> into a P<S, T> via this prism.
This connects prisms to the profunctor hierarchy through Choice.
Given any Choice profunctor P and a value pab: P<A, B>,
transform produces P<S, T> by:
right(pab)lifts toP<Result<T, A>, Result<T, B>>dimappre-composes withmatch_(swapping arms) and post-composes withbuild(reassembling)
The arm-swapping (Ok→Err, Err→Ok in the pre-composition) is necessary
because Choice::right acts on the Err branch of Result.
Examples found in repository?
159fn main() {
160 println!("=== Domain Model with Optics Example ===\n");
161
162 let order = sample_order();
163
164 // 1. Lens: get/set/over
165 println!("--- Lens: basic get/set/over ---");
166 let customer = customer_lens();
167 let address = address_lens();
168 let city = city_lens();
169
170 println!(" Customer name: {}", name_lens().get(&order.customer));
171 println!(" City: {}", city.get(&address.get(&customer.get(&order))));
172
173 // 2. Composed Lens: deep access with .then()
174 println!("\n--- ComposedLens: deep access with .then() ---");
175 let order_city = customer_lens().then(address_lens()).then(city_lens());
176 let order_zip = customer_lens().then(address_lens()).then(zip_lens());
177
178 println!(" Order city: {}", order_city.get(&order));
179 println!(" Order zip: {}", order_zip.get(&order));
180
181 // Deep set
182 let updated = order_city.set(order.clone(), "Shelbyville".into());
183 println!(" After city update: {}", order_city.get(&updated));
184 println!(" Original unchanged: {}", order_city.get(&order));
185
186 // Deep over (modify)
187 let uppercased = order_city.over(order.clone(), |c| c.to_uppercase());
188 println!(" Uppercased city: {}", order_city.get(&uppercased));
189
190 // 3. Lens::transform — reusable update function
191 println!("\n--- Lens::transform — reusable update function ---");
192 let normalize_city: Box<dyn Fn(String) -> String> = Box::new(|c| c.trim().to_uppercase());
193 let normalize_order_city = city_lens().transform::<FnP>(normalize_city);
194 let addr = Address {
195 street: "456 Oak Ave".into(),
196 city: " new york ".into(),
197 zip: "10001".into(),
198 };
199 let normalized = normalize_order_city(addr);
200 println!(" Normalized city: {:?}", normalized.city);
201
202 // 4. Prism: sum type focus
203 println!("\n--- Prism: sum type focus ---");
204 let cc = credit_card_prism();
205 let wallet = wallet_prism();
206 let bank = bank_transfer_prism();
207
208 println!(" Credit card last4: {:?}", cc.preview(&order.payment));
209 println!(" Wallet preview: {:?}", wallet.preview(&order.payment));
210
211 // Prism::review — construct a variant
212 let new_payment = wallet.review(("PayPal".into(), 5000));
213 println!(" New wallet payment: {:?}", new_payment);
214
215 // Prism::over — modify only if matched
216 let updated_payment = cc.over(order.payment.clone(), |(last4, _exp)| {
217 (last4, "01/28".into())
218 });
219 println!(" Updated CC expiry: {:?}", updated_payment);
220
221 // Prism on non-matching variant: passes through unchanged
222 let unchanged = wallet.over(order.payment.clone(), |(prov, bal)| (prov, bal + 1000));
223 println!(" Wallet over on CC (unchanged): {:?}", unchanged);
224
225 // 5. Prism::transform — reusable pattern-matching function
226 println!("\n--- Prism::transform — reusable variant modifier ---");
227 let add_balance: Box<dyn Fn((String, i64)) -> (String, i64)> =
228 Box::new(|(prov, bal)| (prov, bal + 2500));
229 let add_wallet_balance = wallet.transform::<FnP>(add_balance);
230
231 let wallet_payment = Payment::Wallet {
232 provider: "PayPal".into(),
233 balance_cents: 10000,
234 };
235 let topped_up = add_wallet_balance(wallet_payment);
236 println!(" Topped up: {:?}", topped_up);
237
238 // Apply same transform to non-wallet — passes through
239 let still_cc = add_wallet_balance(order.payment.clone());
240 println!(" CC unchanged: {:?}", still_cc);
241
242 // 6. Summary: combine multiple optics
243 println!("\n--- Combining lenses and prisms ---");
244 let orders = vec![
245 sample_order(),
246 Order {
247 id: 1002,
248 customer: Customer {
249 name: "Bob Jones".into(),
250 address: Address {
251 street: "789 Elm St".into(),
252 city: "Capital City".into(),
253 zip: "12345".into(),
254 },
255 },
256 items: vec![Item {
257 name: "Mouse".into(),
258 price_cents: 2999,
259 quantity: 1,
260 }],
261 payment: Payment::Wallet {
262 provider: "Stripe".into(),
263 balance_cents: 50000,
264 },
265 },
266 Order {
267 id: 1003,
268 customer: Customer {
269 name: "Carol White".into(),
270 address: Address {
271 street: "321 Pine Rd".into(),
272 city: "Springfield".into(),
273 zip: "62702".into(),
274 },
275 },
276 items: vec![],
277 payment: Payment::BankTransfer {
278 iban: "DE89370400440532013000".into(),
279 },
280 },
281 ];
282
283 let order_city_lens = customer_lens().then(address_lens()).then(city_lens());
284 println!(" All cities:");
285 for o in &orders {
286 let payment_type = match &o.payment {
287 Payment::CreditCard { .. } => "CC",
288 Payment::BankTransfer { .. } => "Bank",
289 Payment::Wallet { .. } => "Wallet",
290 };
291 println!(
292 " Order #{}: {} ({}, pays via {})",
293 o.id,
294 order_city_lens.get(o),
295 name_lens().get(&o.customer),
296 payment_type
297 );
298 }
299
300 // Find all bank IBANs using Prism
301 println!("\n Bank IBANs:");
302 for o in &orders {
303 if let Some(iban) = bank.preview(&o.payment) {
304 println!(" Order #{}: {}", o.id, iban);
305 }
306 }
307}