use ordofp_core::prelude::*;
fn main() {
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ Welcome to OrdoFP - Functional Programming ║");
println!("║ for Rust with Effect Tracking ║");
println!("╚══════════════════════════════════════════════════════════════╝");
println!();
println!("━━━ Part 1: HList (Heterogeneous Lists) ━━━");
println!();
let my_list = hlist![42, "hello", true, 3.1];
println!(" Created HList: (42, \"hello\", true, 3.1)");
println!(" First element: {}", my_list.head);
println!(" Second element: {}", my_list.tail.head);
println!();
type PersonData = HList![String, u32, bool];
let person: PersonData = hlist!["Alice".to_string(), 30, true];
println!(
" Person data: ({}, {}, {})",
person.head, person.tail.head, person.tail.tail.head
);
println!();
println!("━━━ Part 2: Optics (Lens, Prism, Iso) ━━━");
println!();
#[derive(Clone, Debug)]
struct User {
name: String,
age: u32,
}
let name_lens = lens(
|u: &User| u.name.clone(),
|u: &User, name: String| User { name, age: u.age },
);
let user = User {
name: "Bob".to_string(),
age: 25,
};
println!(" Original user: {user:?}");
println!(" Name via lens: {}", name_lens.get(&user));
let updated = name_lens.set(&user, "Robert".to_string());
println!(" After rename: {updated:?}");
println!();
#[derive(Clone, Debug, PartialEq)]
enum Result2<T, E> {
Ok(T),
Err(E),
}
let ok_prism = prism(
|r: &Result2<i32, &str>| match r {
Result2::Ok(v) => Some(*v),
Result2::Err(_) => None,
},
Result2::Ok,
);
let success = Result2::Ok(42);
let _failure: Result2<i32, &str> = Result2::Err("error"); println!(" Prism preview Ok(42): {:?}", ok_prism.preview(&success));
println!(" Prism review 100: {:?}", ok_prism.review(100));
println!();
println!("━━━ Part 3: Either/Aut (Sum Types) ━━━");
println!();
let success: Aut<&str, i32> = Aut::Dexter(42); let failure: Aut<&str, i32> = Aut::Sinister("error");
println!(" Success value: {success:?}");
println!(" Failure value: {failure:?}");
println!(" Is success right? {}", success.is_dexter());
println!(" Is failure left? {}", failure.is_sinister());
println!();
println!("━━━ Part 4: Easy API (Simplified Effects) ━━━");
println!();
let counter_result = run_with_state(0, |counter| {
*counter += 1;
*counter += 2;
*counter *= 3;
*counter
});
println!(" State computation: 0 -> +1 -> +2 -> *3 = {counter_result}");
#[derive(Clone)]
struct Config {
multiplier: i32,
offset: i32,
}
let config = Config {
multiplier: 2,
offset: 10,
};
let computed = run_with_config(&config, |cfg| {
let base = 5;
base * cfg.multiplier + cfg.offset
});
println!(" Config computation: 5 * 2 + 10 = {computed}");
let mut attempts = 0;
let result: Result<i32, &str> = retry(3, || {
attempts += 1;
if attempts >= 2 {
Ok(42)
} else {
Err("not ready")
}
});
println!(" Retry result (succeeded on attempt {attempts}): {result:?}");
let fallback_result: Result<i32, &str> = fallback(|| Err("primary failed"), || Ok(100));
println!(" Fallback result: {fallback_result:?}");
println!();
println!("━━━ Part 5: IO Computations ━━━");
println!();
let lazy_computation = io(|| {
println!(" (IO computation executed!)");
42
});
println!(" Created lazy IO (not yet executed)");
let io_result = lazy_computation.run();
println!(" IO result: {io_result}");
let chained = io(|| 10).map(|x| x * 2).and_then(|x| io(move || x + 22));
println!(" Chained IO (10 -> *2 -> +22): {}", chained.run());
println!();
println!("━━━ Part 6: Arena Allocation ━━━");
println!();
let arena_result = with_arena(|arena| {
let x = arena.alloc(100);
let y = arena.alloc(200);
let slice = arena.alloc_slice(&[1, 2, 3, 4, 5]);
let sum = *x + *y + slice.iter().sum::<i32>();
println!(" Arena allocated: x=100, y=200, slice=[1,2,3,4,5]");
sum
});
println!(" Arena computation result: {arena_result}");
println!(" (All arena allocations freed automatically)");
println!();
println!("━━━ Part 7: Combinators ━━━");
println!();
let chain_result = chain(|| 1, |x| x + 10, |x| x * 2);
println!(" chain(1, +10, *2) = {chain_result}");
let (a, b) = both(|| 21, || 21);
println!(" both(21, 21) = ({}, {}), sum = {}", a, b, a + b);
let value = 42;
let conditional = when(value > 0, || "positive", || "non-positive");
println!(" when(42 > 0) = \"{conditional}\"");
let squares: Vec<i32> = repeat(5, |i| (i * i) as i32);
println!(" repeat(5, i^2) = {squares:?}");
println!();
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ OrdoFP Features Summary ║");
println!("╠══════════════════════════════════════════════════════════════╣");
println!("║ HList : Type-safe heterogeneous lists ║");
println!("║ Optics : Lens, Prism, Iso for data access ║");
println!("║ Either/Aut : Sum types (Left/Right, Sinister/Dexter) ║");
println!("║ Easy API : State, Reader, Error handling ║");
println!("║ IO : Lazy, composable computations ║");
println!("║ Arena : Fast, scoped memory allocation ║");
println!("║ Combinators: chain, both, when, repeat, etc. ║");
println!("╠══════════════════════════════════════════════════════════════╣");
println!("║ For more examples, see: ║");
println!("║ cargo run --example 09_easy_api ║");
println!("║ cargo run --example 10_vernacular_api ║");
println!("║ cargo run --example 11_effects_intro --features async ║");
println!("╚══════════════════════════════════════════════════════════════╝");
}