///all Traits
#[allow(warnings)]
pub mod traits {
    use std::collections::HashMap;
    use std::thread::JoinHandle;
    use std::{
        any::Any,
        fmt::{Debug, Display},
        path::{Path, PathBuf},
        ptr::null,
        str::FromStr,
    };
    pub trait HtmlTemplate<T, U> {
        fn template_render(&self, context: HashMap<U, U>) -> String;
    }
    impl<T: ToString, U: ToString> HtmlTemplate<T, U> for T {
        fn template_render(&self, context: HashMap<U, U>) -> String {
            let mut output = self.to_string();

            for (key, value) in context {
                let placeholder = format!("{{{{{}}}}}", key.to_string());
                output = output.replace(&placeholder, &value.to_string());
            }
            output
        }
    }

    pub trait Spawn<T: Debug> {
        /// ## spawn
        /// ```ignore
        /// use doe::*;
        /// use doe::keyboard::exit_if_click_esc;
        /// let t1 = run.spawn();
        /// let t2 = exit_if_click_esc.spawn();
        /// t1.join();
        /// t2.join();
        /// ```
        ///
        fn spawn(self) -> JoinHandle<T>;
    }
    impl<T: 'static + Send + Debug, F: FnOnce() -> T + Send + 'static> Spawn<T> for F {
        fn spawn(self) -> JoinHandle<T> {
            std::thread::spawn(self)
        }
    }
    pub trait Decimal {
        fn round_to(&self, by: usize) -> Self
        where
            Self: Sized + Copy,
        {
            *self
        }
        fn random() -> Self;
        ///```ignore
        ///  use doe::*;
        ///  f32::random_in_range(0.0..10.0).dprintln();
        ///  i128::random_in_range(10..99).dprintln();
        /// ```
        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self;
        ///num_to_xl_col
        /// ```ignore
        /// use doe::*;
        /// 0.num_to_xl_col().dprintln();
        /// "A".xl_col_to_num().dprintln();
        /// ```
        ///
        fn num_to_xl_col(&self) -> String;
    }
    impl Decimal for i32 {
        fn num_to_xl_col(&self) -> String {
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;

            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }

            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as i32
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => i32::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as i32 + min
        }
    }
    impl Decimal for i64 {
        fn num_to_xl_col(&self) -> String {
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;

            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }

            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as i64
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => i64::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as i64 + min
        }
    }
    impl Decimal for i128 {
        fn num_to_xl_col(&self) -> String {
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;

            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }

            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as i128
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => i128::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as i128 + min
        }
    }
    impl Decimal for u32 {
        fn num_to_xl_col(&self) -> String {
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;

            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }

            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as u32
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => u32::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as u32 + min
        }
    }
    impl Decimal for u64 {
        fn num_to_xl_col(&self) -> String {
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;

            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }

            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as u64
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => u64::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as u64 + min
        }
    }

    impl Decimal for u128 {
        fn num_to_xl_col(&self) -> String {
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;

            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }

            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as u128
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => u128::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as u128 + min
        }
    }
    impl Decimal for f64 {
        fn num_to_xl_col(&self) -> String {
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;

            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }

            result.chars().rev().collect()
        }
        fn round_to(&self, by: usize) -> f64 {
            let factor = 10.0_f64.powi(by as i32);
            (self * factor).round() / factor
        }
        fn random() -> Self {
            LCG::new().random()
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0.0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => f64::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub) + min
        }
    }

    impl Decimal for f32 {
        fn num_to_xl_col(&self) -> String {
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;

            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }

            result.chars().rev().collect()
        }

        fn round_to(&self, by: usize) -> f32 {
            let factor = 10.0_f32.powi(by as i32);
            (self * factor).round() / factor
        }
        fn random() -> Self {
            LCG::new().random_f32()
        }
        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0.0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => f32::MAX,
            };

            let random = LCG::new().random_f32();
            let sub = max - min;
            (random * sub) + min
        }
    }

    pub trait DynType: ToString {}
    impl<T: ToString> DynType for T {}
    /// this is a ToStringWrapper Struct for implementing Into to Box<dyn DynType>
    #[derive(Debug, Clone)]
    pub struct ToDynType<T: ToString>(pub T);
    impl<T: ToString> Into<Box<dyn DynType>> for ToDynType<T> {
        fn into(self) -> Box<dyn DynType> {
            Box::new(self.0.to_string())
        }
    }
    use std::ops::Deref;

    use crate::LCG;
    pub trait Join {
        fn join(&self, by: &str) -> String;
    }

    impl<T: ToString> Join for [T] {
        fn join(&self, by: &str) -> String {
            self.iter()
                .map(|item| item.to_string())
                .collect::<Vec<String>>()
                .join(by)
        }
    }

    pub trait Vector<T> {
        fn element_to_string(&self) -> Vec<String>;
        fn to_string_lossy(&self) -> String;
        fn split_by_slice(&self, slice: &[T]) -> Vec<Vec<T>>;
        fn random_choose(&self) -> T;
    }
    impl<T: ToString + PartialEq + Clone> Vector<T> for [T] {
        fn element_to_string(&self) -> Vec<String> {
            self.iter().map(|x| x.to_string()).collect::<Vec<String>>()
        }

        fn to_string_lossy(&self) -> String {
            let vec = self
                .iter()
                .map(|x| x.to_string().parse::<u8>().unwrap())
                .collect::<Vec<u8>>();
            String::from_utf8_lossy(&vec).to_string()
        }

        fn split_by_slice(&self, slice: &[T]) -> Vec<Vec<T>> {
            let mut result = Vec::new();
            let mut start = 0;

            while let Some(index) = self[start..]
                .windows(slice.len())
                .position(|window| window == slice)
            {
                let end = start + index;
                result.push(self[start..end].to_vec());
                start = end + slice.len();
            }

            result.push(self[start..].to_vec());

            result
        }

        ///random_choose
        ///```rust
        ///use doe::*;  
        ///let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        ///v.random_choose().dprintln();
        /// ```
        ///
        fn random_choose(&self) -> T {
            use crate::LCG;
            let lcg = LCG::new();
            let random_index = lcg.random_in_range(0..self.len() as i128);
            self.clone().get(random_index as usize).unwrap().to_owned()
        }
    }
    pub trait Str {
        fn cut(&self, start: i32, end: i32, step: usize) -> String;

        fn format(&self, targets: Vec<(Box<dyn ToString>, Box<dyn ToString>)>) -> String;
        /// str String to Path
        fn to_path(&self) -> Box<Path>;
        /// str String to PathBuf
        fn to_path_buf(&self) -> PathBuf;
        ///split string by delimiter into Vec<String>
        fn split_to_vec(&self, delimiter: &str) -> Vec<String>;
        ///string into Box<str>
        fn to_box(&self) -> Box<str>;
        ///push back item to string
        fn push_back(&self, item: impl ToString) -> String;
        ///push front item to string
        fn push_front(&self, item: impl ToString) -> String;
        ///is equal return true
        fn is_equal(&self, other: &Self) -> bool;
        //add two string
        fn add(&self, other: &Self) -> String;
        //reverse string
        fn reverse(&self) -> String;
        //capitalize string
        fn capitalize(&self) -> String;
        /// trim start of string
        fn trim_lines(&self) -> String;
        /// convert xl col to num
        /// ```ignore
        /// use doe::*;
        /// 0.num_to_xl_col().dprintln();
        /// "A".xl_col_to_num().dprintln();
        /// ```
        ///
        fn xl_col_to_num(&self) -> usize;
        /// convert 'A1' to (col, row) = (0,1)
        fn coordinate_to_position(&self) -> (usize, usize);
    }

    impl<S: ToString> Str for S {
        fn coordinate_to_position(&self) -> (usize, usize) {
            let coord_str = self.to_string();
            let mut col_str = String::new();
            let mut row_str = String::new();
            for c in coord_str.chars() {
                if c.is_digit(10) {
                    row_str.push(c);
                } else {
                    col_str.push(c);
                }
            }
            let col_num = col_str.xl_col_to_num();
            let row_num = row_str.parse::<usize>().unwrap();
            (col_num, row_num)
        }
        fn xl_col_to_num(&self) -> usize {
            let col_str = self.to_string().to_uppercase();
            let mut col_num = 0;
            for (i, c) in col_str.chars().enumerate() {
                if (c as u8 as i8 - 'A' as u8 as i8) >= 0 {
                    let offset = (c as u8 - b'A') as usize + 1;
                    col_num = col_num * 26 + offset;
                }
            }
            col_num - 1
        }
        //add two string
        fn add(&self, other: &Self) -> String {
            format!("{}{}", self.to_string(), other.to_string())
        }
        ///is equal return true
        fn is_equal(&self, other: &Self) -> bool {
            self.to_string() == other.to_string()
        }
        ///push back item to string
        fn push_back(&self, item: impl ToString) -> String {
            format!("{}{}", self.to_string(), item.to_string())
        }

        ///push front item to string
        fn push_front(&self, item: impl ToString) -> String {
            format!("{}{}", item.to_string(), self.to_string().to_string())
        }
        /// ## implment cut format for str and String
        /// ```rust
        ///fn main() {
        ///    use doe::Str;
        ///    use doe::targets;
        ///    let a = "this is a demo {}";
        ///    let c = a.cut(-1,-2,1);
        ///    let f = a.format(targets!("{}"=>"this is a demo"));
        ///    println!("{:?}",f);
        ///    println!("{:?}",c);
        ///}
        /// ```
        fn cut(&self, start: i32, end: i32, step: usize) -> String {
            let mut res = String::new();
            if start >= 0 && end >= 0 && start <= end {
                let start = start as usize;
                let end = end as usize;
                for (i, c) in self.to_string().chars().enumerate().step_by(step) {
                    if i >= start && i <= end {
                        res.push(c);
                    }
                }
            } else if start < 0 && end < 0 {
                if start > end {
                    let start = self.to_string().len() as i32 + end;
                    let end = self.to_string().len() as i32 + start;
                    let start = start as usize;
                    let end = end as usize;
                    for (i, c) in self.to_string().chars().enumerate().step_by(step) {
                        if i >= start && i <= end {
                            res.push(c);
                        }
                    }
                } else {
                    let start = self.to_string().len() as i32 + start;
                    let end = self.to_string().len() as i32 + end;
                    let start = start as usize;
                    let end = end as usize;
                    for (i, c) in self.to_string().chars().enumerate().step_by(step) {
                        if i >= start && i <= end {
                            res.push(c);
                        }
                    }
                }
            } else if start > 0 && end < 0 {
                let start = start as usize;
                let end = self.to_string().len() as i32 + end;
                let end = end as usize;
                for (i, c) in self.to_string().chars().enumerate().step_by(step) {
                    if i >= start && i <= end {
                        res.push(c);
                    }
                }
            }
            res
        }

        /// ## implment format for str and String
        /// ```rust
        ///fn main() {
        ///    use doe::*;
        ///    "this is a {s},I like Trait Object {p}%"
        ///    .format(vec![(Box::new("{s}"),Box::new("demo")),(Box::new("{p}"),Box::new(100))]).println();//this is a demo,I like Trait Object 100%
        ///     use doe::targets;
        ///     "this is a {d},I like Trait Object {p}}%"
        ///     .format(targets!{"{d}"=>"demo","{p}"=>100})
        ///     .println(); //this is a demo,I like Trait Object 100%
        ///     
        ///     let a = "demo";
        ///     let b_a: Box<str> = a.to_box();
        ///     b_a.as_ref().dprintln();
        ///}
        /// ```
        fn format(&self, targets: Vec<(Box<dyn ToString>, Box<dyn ToString>)>) -> String {
            let mut s_mut = self.to_string().to_string();
            for t in targets {
                s_mut = s_mut.replace(&t.0.deref().to_string(), &t.1.deref().to_string());
            }
            s_mut
        }
        fn to_path(&self) -> Box<Path> {
            Path::new(&self.to_string()).to_owned().into()
        }
        fn to_path_buf(&self) -> PathBuf {
            PathBuf::from_str(&self.to_string()).unwrap()
        }
        fn split_to_vec(&self, delimiter: &str) -> Vec<String> {
            crate::split_to_vec!(self.to_string(), delimiter)
        }
        fn to_box(&self) -> Box<str> {
            Box::from(self.to_string())
        }
        ///reverse string
        /// ```rust
        /// use doe::Str;
        /// use doe::*;
        /// "a string".reverse().println(); //"gnirts a"
        /// ```
        ///
        fn reverse(&self) -> String {
            let mut s = self.to_string().chars().rev().collect::<Vec<_>>();
            s.join("")
        }
        //capitalize string
        fn capitalize(&self) -> String {
            if let Some(c) = self.to_string().chars().next() {
                let first_letter_capitalized = c.to_uppercase().collect::<String>();
                let rest_of_string = &self.to_string()[1..];
                return format!("{}{}", first_letter_capitalized, rest_of_string);
            }
            self.to_string()
        }

        fn trim_lines(&self) -> String {
            self.split_to_vec("\n")
                .iter()
                .map(|s| s.trim().to_string())
                .collect::<Vec<_>>()
                .join("\n")
        }
    }
    pub trait Then {
        fn then(&self, run: impl Fn()) -> &Self;
    }

    impl<T> Then for T {
        fn then(&self, run: impl Fn()) -> &Self {
            run();
            self
        }
    }
    pub trait Sleep {
        fn sleep(&self, secs: f64);
    }
    impl<T> Sleep for T {
        fn sleep(&self, secs: f64) {
            use std::thread::sleep;
            use std::time::Duration;
            sleep(Duration::from_secs_f64(secs));
        }
    }

    /// A trait for impl Debug
    pub trait DebugPrint {
        /// debug print
        /// ```rust
        /// use doe::DebugPrint;
        /// let get = |url:&str|url.to_string().dprint();
        /// ```
        fn dprint(&self);
        /// debug eprint
        /// ```rust
        /// use doe::DebugPrint;
        /// let get = |url:&str|url.to_string().deprint();
        /// ```
        fn deprint(&self);
        /// debug println
        /// ```rust
        /// use doe::DebugPrint;
        /// let get = |url:&str|url.to_string().dprintln();
        /// ```
        fn dprintln(&self);
        /// debug eprintln
        /// ```rust
        /// use doe::DebugPrint;
        /// let get = |url:&str|url.to_string().deprintln();
        /// ```
        fn deprintln(&self);
        /// ```rust
        /// fn main() {
        ///     use doe::DebugPrint;
        ///     #[derive(Debug)]
        ///     struct Demo{}
        ///     let d = Demo{};
        ///     d.dbg();
        /// }
        /// ```
        fn dbg(&self);
    }
    impl<T> DebugPrint for T
    where
        T: Debug,
    {
        fn dprint(&self) {
            print!("{:?}", self);
        }
        fn deprint(&self) {
            eprint!("{:?}", self);
        }

        fn dprintln(&self) {
            println!("{:?}", self);
        }
        fn deprintln(&self) {
            eprintln!("{:?}", self);
        }
        fn dbg(&self) {
            dbg!(self);
        }
    }
    pub trait Print {
        /// ```rust
        /// use doe::Print;
        /// let get = |url:&str|url.to_string().print();
        /// ```
        fn print(&self);
        /// ```rust
        /// use doe::Print;
        /// let get = |url:&str|url.to_string().print();
        /// ```
        fn eprint(&self);
        /// ```rust
        /// use doe::Print;
        /// let get = |url:&str|url.to_string().println();
        /// ```
        fn println(&self);
        /// ```rust
        /// use doe::Print;
        /// let get = |url:&str|url.to_string().println();
        /// ```
        fn eprintln(&self);
    }
    impl<T> Print for T
    where
        T: Display,
    {
        fn print(&self) {
            print!("{}", self);
        }
        fn eprint(&self) {
            eprint!("{}", self);
        }

        fn println(&self) {
            println!("{}", self);
        }
        fn eprintln(&self) {
            eprintln!("{}", self);
        }
    }
    ///IsThen
    /// ```rust
    ///use doe::*;
    ///let a = Some(1);
    ///let b: Result<i32, Box<dyn std::error::Error>> = Err("error".into());
    ///b.is_ok_then(|s| {
    ///}).is_none_then(|| {
    ///    println!("NONE");
    ///});
    /// ```
    pub trait IsThen<T> {
        fn is_some_then(self, f: impl FnOnce(T) -> T) -> Option<T>;
        fn is_none_then(self, f: impl FnOnce());
        fn is_ok_then(self, f: impl FnOnce(T)) -> Option<T>;
        fn is_err_then(self, f: impl FnOnce());
    }

    impl<T: Clone, U> IsThen<T> for Result<T, U> {
        fn is_some_then(self, f: impl FnOnce(T) -> T) -> Option<T> {
            match self {
                Ok(value) => Some(f(value)),
                Err(_) => None,
            }
        }

        fn is_none_then(self, f: impl FnOnce()) {
            if self.is_err() {
                f();
            }
        }

        fn is_ok_then(self, f: impl FnOnce(T)) -> Option<T> {
            match self {
                Ok(value) => {
                    f(value.clone());
                    Some(value)
                }
                Err(_) => None,
            }
        }

        fn is_err_then(self, f: impl FnOnce()) {
            if self.is_err() {
                f();
            }
        }
    }

    impl<T: Clone> IsThen<T> for Option<T> {
        fn is_some_then(self, f: impl FnOnce(T) -> T) -> Option<T> {
            match self {
                Some(value) => Some(f(value)),
                None => None,
            }
        }

        fn is_none_then(self, f: impl FnOnce()) {
            if self.is_none() {
                f();
            }
        }

        fn is_ok_then(self, f: impl FnOnce(T)) -> Option<T> {
            match self {
                Some(value) => {
                    f(value.clone());
                    Some(value)
                }
                None => None,
            }
        }

        fn is_err_then(self, f: impl FnOnce()) {
            if self.is_none() {
                f();
            }
        }
    }

    pub mod hkt {
        //! The `HKT` trait enables emulation of higher-kinded types in Rust.
        //!
        //! Higher-kinded types (HKTs) are type constructors that take a type and return
        //! another type. Rust does not directly support higher-kinded types, but we can
        //! emulate them using associated types.
        //!
        //! This module provides the `HKT` trait and related traits that form the
        //! foundation for higher-kinded polymorphism in the Rustica library.

        use std::marker::PhantomData;

        /// A trait for types that can be treated as higher-kinded types.
        pub trait HKT {
            /// The type contained in this HKT.
            type Source;

            /// The same HKT but containing type `NewType` instead of `Source`.
            type Output<NewType>: HKT<Source = NewType>;
        }

        /// A trait for higher-kinded types that have two type parameters.
        pub trait BinaryHKT: HKT {
            /// The second type parameter of this HKT.
            type Source2;

            /// The same HKT but with both type parameters replaced.
            type BinaryOutput<Type1, Type2>: BinaryHKT<Source = Type1, Source2 = Type2>;

            /// Maps a function over the second type parameter.
            fn map_second<F, NewType2>(&self, f: F) -> Self::BinaryOutput<Self::Source, NewType2>
            where
                F: Fn(&Self::Source2) -> NewType2,
                Self::Source: Clone,
                Self::Source2: Clone,
                NewType2: Clone;

            /// Maps a function over the second type parameter, consuming the HKT.
            fn map_second_owned<F, NewType2>(
                self,
                f: F,
            ) -> Self::BinaryOutput<Self::Source, NewType2>
            where
                F: Fn(Self::Source2) -> NewType2,
                NewType2: Clone;
        }

        // Implementations for common Rust types

        impl<T> HKT for Option<T> {
            type Source = T;
            type Output<U> = Option<U>;
        }

        impl<T, E> HKT for Result<T, E> {
            type Source = T;
            type Output<U> = Result<U, E>;
        }

        impl<T> HKT for Vec<T> {
            type Source = T;
            type Output<U> = Vec<U>;
        }

        impl<T> HKT for Box<T> {
            type Source = T;
            type Output<U> = Box<U>;
        }

        /// A phantom type used to represent a higher-kinded type at the type level.
        #[derive(Debug, Clone, PartialEq, Eq)]
        pub struct HKTType<H, T>(PhantomData<H>, PhantomData<T>);

        impl<H, T> Default for HKTType<H, T> {
            #[inline]
            fn default() -> Self {
                Self::new()
            }
        }

        impl<H, T> HKTType<H, T> {
            #[inline]
            pub fn new() -> Self {
                Self(PhantomData, PhantomData)
            }
        }
    }

    pub mod functor {
        //! Functor trait and extensions for higher-kinded types.

        use crate::hkt::HKT;

        /// A trait for functors, which are type constructors that support mapping over values.
        pub trait Functor: HKT {
            /// Maps a function over the values in a functor without consuming it.
            fn fmap<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> B;

            /// Maps a function over the values in a functor, consuming it.
            fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
            where
                F: Fn(Self::Source) -> B,
                Self: Sized;

            /// Replaces all values in the functor with a constant value.
            #[inline]
            fn replace<B>(&self, value: &B) -> Self::Output<B>
            where
                B: Clone,
            {
                self.fmap(|_| value.clone())
            }

            /// Replaces all values in the functor with a constant value, consuming it.
            #[inline]
            fn replace_owned<B>(self, value: B) -> Self::Output<B>
            where
                B: Clone,
                Self: Sized,
            {
                self.fmap_owned(|_| value.clone())
            }

            /// Void functor - discards the values and replaces them with unit.
            #[inline]
            fn void(&self) -> Self::Output<()> {
                self.fmap(|_| ())
            }

            /// Void functor - discards the values and replaces them with unit, consuming it.
            #[inline]
            fn void_owned(self) -> Self::Output<()>
            where
                Self: Sized,
            {
                self.fmap_owned(|_| ())
            }
        }

        /// Extension trait for functors providing additional utility methods.
        pub trait FunctorExt: Functor {
            /// Transforms values with a fallible function, handling errors by providing a default value.
            #[inline]
            fn try_map_or<B, E, F>(&self, default: B, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> Result<B, E>,
                B: Clone,
            {
                self.fmap(|a| match f(a) {
                    Ok(b) => b,
                    Err(_) => default.clone(),
                })
            }

            /// Transforms values with a fallible function, handling errors with a provided function.
            #[inline]
            fn try_map_or_else<B, E, D, F>(&self, default_fn: D, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> Result<B, E>,
                B: Clone,
                D: Fn(&E) -> B,
            {
                self.fmap(|a| match f(a) {
                    Ok(b) => b,
                    Err(e) => default_fn(&e),
                })
            }

            /// Transforms values with a function that might return None, filtering out None results.
            fn filter_map<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> Option<B>;
        }

        impl<T> Functor for Vec<T> {
            #[inline]
            fn fmap<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> B,
            {
                self.iter().map(f).collect()
            }

            #[inline]
            fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
            where
                F: Fn(Self::Source) -> B,
                Self: Sized,
            {
                self.into_iter().map(f).collect()
            }
        }

        impl<T> FunctorExt for Vec<T> {
            #[inline]
            fn filter_map<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: FnMut(&Self::Source) -> Option<B>,
            {
                self.iter().filter_map(f).collect()
            }

            #[inline]
            fn try_map_or<B, E, F>(&self, default: B, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> Result<B, E>,
                B: Clone,
            {
                self.iter()
                    .map(|x| match f(x) {
                        Ok(b) => b,
                        Err(_) => default.clone(),
                    })
                    .collect()
            }

            #[inline]
            fn try_map_or_else<B, E, D, F>(&self, default_fn: D, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> Result<B, E>,
                D: Fn(&E) -> B,
            {
                self.iter()
                    .map(|x| match f(x) {
                        Ok(b) => b,
                        Err(e) => default_fn(&e),
                    })
                    .collect()
            }
        }

        impl<T> Functor for Option<T> {
            #[inline]
            fn fmap<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> B,
            {
                self.as_ref().map(f)
            }

            #[inline]
            fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
            where
                F: Fn(Self::Source) -> B,
                Self: Sized,
            {
                self.map(f)
            }
        }

        impl<T> FunctorExt for Option<T> {
            #[inline]
            fn filter_map<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: FnOnce(&Self::Source) -> Option<B>,
            {
                self.as_ref().and_then(f)
            }

            #[inline]
            fn try_map_or<B, E, F>(&self, default: B, f: F) -> Self::Output<B>
            where
                F: FnOnce(&Self::Source) -> Result<B, E>,
                B: Clone,
            {
                match self {
                    Some(value) => match f(value) {
                        Ok(b) => Some(b),
                        Err(_) => Some(default.clone()),
                    },
                    None => None,
                }
            }

            #[inline]
            fn try_map_or_else<B, E, D, F>(&self, default_fn: D, f: F) -> Self::Output<B>
            where
                F: FnOnce(&Self::Source) -> Result<B, E>,
                D: Fn(&E) -> B,
            {
                match self {
                    Some(value) => match f(value) {
                        Ok(b) => Some(b),
                        Err(e) => Some(default_fn(&e)),
                    },
                    None => None,
                }
            }
        }

        impl<A, E: Clone> Functor for Result<A, E> {
            #[inline]
            fn fmap<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> B,
            {
                match self {
                    Ok(value) => Ok(f(value)),
                    Err(e) => Err(e.clone()),
                }
            }

            #[inline]
            fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
            where
                F: Fn(Self::Source) -> B,
                Self: Sized,
            {
                match self {
                    Ok(value) => Ok(f(value)),
                    Err(e) => Err(e),
                }
            }
        }

        impl<A, E: Clone + Default> FunctorExt for Result<A, E> {
            #[inline]
            fn filter_map<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: FnOnce(&Self::Source) -> Option<B>,
            {
                match self {
                    Ok(value) => match f(value) {
                        Some(b) => Ok(b),
                        None => Err(E::default()),
                    },
                    Err(e) => Err(e.clone()),
                }
            }

            #[inline]
            fn try_map_or<B, E2, F>(&self, default: B, f: F) -> Self::Output<B>
            where
                F: FnOnce(&Self::Source) -> Result<B, E2>,
                B: Clone,
            {
                match self {
                    Ok(value) => match f(value) {
                        Ok(b) => Ok(b),
                        Err(_) => Ok(default.clone()),
                    },
                    Err(e) => Err(e.clone()),
                }
            }

            #[inline]
            fn try_map_or_else<B, E2, D, F>(&self, default_fn: D, f: F) -> Self::Output<B>
            where
                F: FnOnce(&Self::Source) -> Result<B, E2>,
                D: Fn(&E2) -> B,
            {
                match self {
                    Ok(value) => match f(value) {
                        Ok(b) => Ok(b),
                        Err(e) => Ok(default_fn(&e)),
                    },
                    Err(e) => Err(e.clone()),
                }
            }
        }
    }

    pub mod error {
        //! Error types for the Either datatype.

        /// Error type for Either unwrap operations.
        #[derive(Debug, Clone, PartialEq, Eq)]
        pub enum EitherError {
            /// Expected a Left value but found Right
            ExpectedLeft,
            /// Expected a Right value but found Left
            ExpectedRight,
        }

        impl std::fmt::Display for EitherError {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                match self {
                    EitherError::ExpectedLeft => write!(f, "expected Left but found Right"),
                    EitherError::ExpectedRight => write!(f, "expected Right but found Left"),
                }
            }
        }

        impl std::error::Error for EitherError {}
    }

    pub mod either {
        //! The Either type represents values with two possibilities.

        use crate::error::EitherError;
        use crate::functor::{Functor, FunctorExt};
        use crate::hkt::{BinaryHKT, HKT};

        /// The `Either` type represents values with two possibilities: a value of type `L` or a value of type `R`.
        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
        pub enum Either<L, R> {
            /// Contains a value of type `L`
            Left(L),
            /// Contains a value of type `R`
            Right(R),
        }

        // Helper functions
        fn either_to_result<L, R>(either: Either<L, R>) -> Result<R, L> {
            match either {
                Either::Left(l) => Err(l),
                Either::Right(r) => Ok(r),
            }
        }

        fn result_to_either<L, R>(result: Result<R, L>) -> Either<L, R> {
            match result {
                Ok(r) => Either::Right(r),
                Err(l) => Either::Left(l),
            }
        }

        // Iterator types
        /// Iterator over the left value of an Either.
        pub struct EitherLeftIter<L> {
            left: Option<L>,
        }

        impl<L> Iterator for EitherLeftIter<L> {
            type Item = L;

            fn next(&mut self) -> Option<Self::Item> {
                self.left.take()
            }
        }

        /// Iterator over a reference to the left value of an Either.
        pub struct EitherLeftIterRef<'a, L> {
            left: Option<&'a L>,
        }

        impl<'a, L> Iterator for EitherLeftIterRef<'a, L> {
            type Item = &'a L;

            fn next(&mut self) -> Option<Self::Item> {
                self.left.take()
            }
        }

        /// Iterator over a mutable reference to the left value of an Either.
        pub struct EitherLeftIterMut<'a, L> {
            left: Option<&'a mut L>,
        }

        impl<'a, L> Iterator for EitherLeftIterMut<'a, L> {
            type Item = &'a mut L;

            fn next(&mut self) -> Option<Self::Item> {
                self.left.take()
            }
        }

        /// Iterator over the right value of an Either.
        pub struct EitherRightIter<R> {
            right: Option<R>,
        }

        impl<R> Iterator for EitherRightIter<R> {
            type Item = R;

            fn next(&mut self) -> Option<Self::Item> {
                self.right.take()
            }
        }

        /// Iterator over a reference to the right value of an Either.
        pub struct EitherRightIterRef<'a, R> {
            right: Option<&'a R>,
        }

        impl<'a, R> Iterator for EitherRightIterRef<'a, R> {
            type Item = &'a R;

            fn next(&mut self) -> Option<Self::Item> {
                self.right.take()
            }
        }

        /// Iterator over a mutable reference to the right value of an Either.
        pub struct EitherRightIterMut<'a, R> {
            right: Option<&'a mut R>,
        }

        impl<'a, R> Iterator for EitherRightIterMut<'a, R> {
            type Item = &'a mut R;

            fn next(&mut self) -> Option<Self::Item> {
                self.right.take()
            }
        }

        impl<L, R> IntoIterator for Either<L, R> {
            type Item = R;
            type IntoIter = EitherRightIter<R>;

            fn into_iter(self) -> Self::IntoIter {
                match self {
                    Either::Left(_) => EitherRightIter { right: None },
                    Either::Right(r) => EitherRightIter { right: Some(r) },
                }
            }
        }

        impl<'a, L, R> IntoIterator for &'a Either<L, R> {
            type Item = &'a R;
            type IntoIter = EitherRightIterRef<'a, R>;

            fn into_iter(self) -> Self::IntoIter {
                match self {
                    Either::Left(_) => EitherRightIterRef { right: None },
                    Either::Right(r) => EitherRightIterRef { right: Some(r) },
                }
            }
        }

        impl<'a, L, R> IntoIterator for &'a mut Either<L, R> {
            type Item = &'a mut R;
            type IntoIter = EitherRightIterMut<'a, R>;

            fn into_iter(self) -> Self::IntoIter {
                match self {
                    Either::Left(_) => EitherRightIterMut { right: None },
                    Either::Right(r) => EitherRightIterMut { right: Some(r) },
                }
            }
        }

        // HKT implementations for Either
        // Note: Following the convention, Source = R (right/primary), Source2 = L (left/secondary)
        impl<L, R> HKT for Either<L, R> {
            type Source = R;
            type Output<U> = Either<L, U>;
        }

        impl<L, R> BinaryHKT for Either<L, R> {
            type Source2 = L;
            type BinaryOutput<Type1, Type2> = Either<Type2, Type1>;

            fn map_second<F, NewType2>(&self, f: F) -> Self::BinaryOutput<Self::Source, NewType2>
            where
                F: Fn(&Self::Source2) -> NewType2,
                Self::Source: Clone,
                Self::Source2: Clone,
                NewType2: Clone,
            {
                match self {
                    Either::Left(l) => Either::Left(f(l)),
                    Either::Right(r) => Either::Right(r.clone()),
                }
            }

            fn map_second_owned<F, NewType2>(
                self,
                f: F,
            ) -> Self::BinaryOutput<Self::Source, NewType2>
            where
                F: Fn(Self::Source2) -> NewType2,
                NewType2: Clone,
            {
                match self {
                    Either::Left(l) => Either::Left(f(l)),
                    Either::Right(r) => Either::Right(r),
                }
            }
        }

        // Functor implementation for Either
        impl<L: Clone, R> Functor for Either<L, R> {
            #[inline]
            fn fmap<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: Fn(&Self::Source) -> B,
            {
                match self {
                    Either::Left(l) => Either::Left(l.clone()),
                    Either::Right(r) => Either::Right(f(r)),
                }
            }

            #[inline]
            fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
            where
                F: Fn(Self::Source) -> B,
                Self: Sized,
            {
                match self {
                    Either::Left(l) => Either::Left(l),
                    Either::Right(r) => Either::Right(f(r)),
                }
            }
        }

        impl<L: Clone + Default, R> FunctorExt for Either<L, R> {
            #[inline]
            fn filter_map<B, F>(&self, f: F) -> Self::Output<B>
            where
                F: FnOnce(&Self::Source) -> Option<B>,
            {
                match self {
                    Either::Left(l) => Either::Left(l.clone()),
                    Either::Right(r) => match f(r) {
                        Some(b) => Either::Right(b),
                        None => Either::Left(L::default()),
                    },
                }
            }

            #[inline]
            fn try_map_or<B, E, F>(&self, default: B, f: F) -> Self::Output<B>
            where
                F: FnOnce(&Self::Source) -> Result<B, E>,
                B: Clone,
            {
                match self {
                    Either::Left(l) => Either::Left(l.clone()),
                    Either::Right(r) => match f(r) {
                        Ok(b) => Either::Right(b),
                        Err(_) => Either::Right(default.clone()),
                    },
                }
            }

            #[inline]
            fn try_map_or_else<B, E, D, F>(&self, default_fn: D, f: F) -> Self::Output<B>
            where
                F: FnOnce(&Self::Source) -> Result<B, E>,
                B: Clone,
                D: Fn(&E) -> B,
            {
                match self {
                    Either::Left(l) => Either::Left(l.clone()),
                    Either::Right(r) => match f(r) {
                        Ok(b) => Either::Right(b),
                        Err(e) => Either::Right(default_fn(&e)),
                    },
                }
            }
        }

        impl<L, R> Either<L, R> {
            /// Creates a new `Either::Left` containing the given value.
            #[inline]
            pub const fn left(l: L) -> Self {
                Either::Left(l)
            }

            /// Creates a new `Either::Right` containing the given value.
            #[inline]
            pub const fn right(r: R) -> Self {
                Either::Right(r)
            }

            /// Returns `true` if this is a `Left` value.
            #[inline]
            pub const fn is_left(&self) -> bool {
                matches!(self, Either::Left(_))
            }

            /// Returns `true` if this is a `Right` value.
            #[inline]
            pub const fn is_right(&self) -> bool {
                matches!(self, Either::Right(_))
            }

            /// Maps a function over the left value, leaving a right value unchanged.
            #[inline]
            pub fn fmap_left<T, F>(self, f: F) -> Either<T, R>
            where
                F: Fn(L) -> T,
            {
                match self {
                    Either::Left(l) => Either::Left(f(l)),
                    Either::Right(r) => Either::Right(r),
                }
            }

            /// Maps a function over the right value, leaving a left value unchanged.
            #[inline]
            pub fn fmap_right<T, F>(self, mut f: F) -> Either<L, T>
            where
                F: FnMut(R) -> T,
            {
                match self {
                    Either::Left(l) => Either::Left(l),
                    Either::Right(r) => Either::Right(f(r)),
                }
            }

            /// Extracts the left value, panicking if this is a `Right`.
            #[inline]
            pub fn unwrap_left(self) -> L {
                match self {
                    Either::Left(l) => l,
                    Either::Right(_) => panic!("called unwrap_left on Right value"),
                }
            }

            /// Extracts the right value, panicking if this is a `Left`.
            #[inline]
            pub fn unwrap_right(self) -> R {
                match self {
                    Either::Right(r) => r,
                    Either::Left(_) => panic!("called unwrap_right on Left value"),
                }
            }

            /// Unwraps an either, yielding the content of a `Right` or panicking.
            #[inline]
            pub fn unwrap(self) -> R {
                match self {
                    Either::Right(r) => r,
                    Either::Left(_) => panic!("called `Either::unwrap()` on a `Left` value"),
                }
            }

            /// Unwraps an either, yielding the content of a `Right` or a default value.
            #[inline]
            pub fn unwrap_or(self, default: R) -> R {
                match self {
                    Either::Right(r) => r,
                    Either::Left(_) => default,
                }
            }

            /// Returns the contained `Left` value, consuming the `self` value.
            #[inline]
            pub fn left_value(self) -> L
            where
                Self: Sized,
            {
                match self {
                    Either::Left(l) => l,
                    Either::Right(_) => panic!("called left_value on Right value"),
                }
            }

            /// Returns the contained `Right` value, consuming the `self` value.
            #[inline]
            pub fn right_value(self) -> R {
                match self {
                    Either::Right(r) => r,
                    Either::Left(_) => panic!("called right_value on Left value"),
                }
            }

            /// Returns a reference to the `Left` value.
            #[inline]
            pub fn left_ref(&self) -> &L {
                match self {
                    Either::Left(l) => l,
                    Either::Right(_) => panic!("Called left_ref on an Either::Right"),
                }
            }

            /// Returns a reference to the `Right` value.
            #[inline]
            pub fn right_ref(&self) -> &R {
                match self {
                    Either::Right(r) => r,
                    Either::Left(_) => panic!("Called right_ref() on a Left value"),
                }
            }

            /// Returns the contained `Right` value or a default.
            #[inline]
            pub fn right_or(self, default: R) -> R {
                match self {
                    Either::Right(r) => r,
                    Either::Left(_) => default,
                }
            }

            /// Returns the contained `Left` value or a default.
            #[inline]
            pub fn left_or(self, default: L) -> L {
                match self {
                    Either::Left(l) => l,
                    Either::Right(_) => default,
                }
            }

            /// Returns the contained `Right` value as an Option.
            #[inline]
            pub fn right_option(self) -> Option<R> {
                match self {
                    Either::Right(r) => Some(r),
                    Either::Left(_) => None,
                }
            }

            /// Converts this `Either` to a `Result`.
            #[inline]
            pub fn to_result(self) -> Result<R, L> {
                either_to_result(self)
            }

            /// Creates an `Either` from a `Result`.
            #[inline]
            pub fn from_result(result: Result<R, L>) -> Self {
                result_to_either(result)
            }

            /// Returns an iterator over the left value, consuming self.
            pub fn left_iter(self) -> EitherLeftIter<L> {
                match self {
                    Either::Left(l) => EitherLeftIter { left: Some(l) },
                    Either::Right(_) => EitherLeftIter { left: None },
                }
            }

            /// Returns an iterator over a reference to the left value.
            pub fn left_iter_ref(&self) -> EitherLeftIterRef<'_, L> {
                match self {
                    Either::Left(l) => EitherLeftIterRef { left: Some(l) },
                    Either::Right(_) => EitherLeftIterRef { left: None },
                }
            }

            /// Returns an iterator over a mutable reference to the left value.
            pub fn left_iter_mut(&mut self) -> EitherLeftIterMut<'_, L> {
                match self {
                    Either::Left(l) => EitherLeftIterMut { left: Some(l) },
                    Either::Right(_) => EitherLeftIterMut { left: None },
                }
            }

            /// Returns the contained `Left` value as an Option.
            pub fn left_option(self) -> Option<L> {
                self.left_iter().next()
            }

            /// Returns a mutable reference to the `Left` value, panicking if not present.
            pub fn left_mut(&mut self) -> &mut L {
                match self {
                    Either::Left(l) => l,
                    Either::Right(_) => panic!("Called left_mut() on a Right value"),
                }
            }

            /// Safely extracts the left value.
            #[inline]
            pub fn try_unwrap_left(self) -> Result<L, EitherError> {
                match self {
                    Either::Left(l) => Ok(l),
                    Either::Right(_) => Err(EitherError::ExpectedLeft),
                }
            }

            /// Safely extracts the right value.
            #[inline]
            pub fn try_unwrap_right(self) -> Result<R, EitherError> {
                match self {
                    Either::Right(r) => Ok(r),
                    Either::Left(_) => Err(EitherError::ExpectedRight),
                }
            }

            /// Safely gets a reference to the left value.
            #[inline]
            pub fn try_left_ref(&self) -> Result<&L, EitherError> {
                match self {
                    Either::Left(l) => Ok(l),
                    Either::Right(_) => Err(EitherError::ExpectedLeft),
                }
            }

            /// Safely gets a reference to the right value.
            #[inline]
            pub fn try_right_ref(&self) -> Result<&R, EitherError> {
                match self {
                    Either::Right(r) => Ok(r),
                    Either::Left(_) => Err(EitherError::ExpectedRight),
                }
            }

            /// Returns a mutable reference to the `Right` value, panicking if not present.
            pub fn right_mut(&mut self) -> &mut R {
                match self {
                    Either::Right(r) => r,
                    Either::Left(_) => panic!("Called right_mut() on a Left value"),
                }
            }

            /// Safely gets a mutable reference to the left value.
            #[inline]
            pub fn try_left_mut(&mut self) -> Result<&mut L, EitherError> {
                match self {
                    Either::Left(l) => Ok(l),
                    Either::Right(_) => Err(EitherError::ExpectedLeft),
                }
            }

            /// Safely gets a mutable reference to the right value.
            #[inline]
            pub fn try_right_mut(&mut self) -> Result<&mut R, EitherError> {
                match self {
                    Either::Right(r) => Ok(r),
                    Either::Left(_) => Err(EitherError::ExpectedRight),
                }
            }

            /// Returns an iterator over the right value, consuming self.
            pub fn right_iter(self) -> EitherRightIter<R> {
                match self {
                    Either::Left(_) => EitherRightIter { right: None },
                    Either::Right(r) => EitherRightIter { right: Some(r) },
                }
            }

            /// Returns an iterator over a reference to the right value.
            pub fn right_iter_ref(&self) -> EitherRightIterRef<'_, R> {
                match self {
                    Either::Left(_) => EitherRightIterRef { right: None },
                    Either::Right(r) => EitherRightIterRef { right: Some(r) },
                }
            }

            /// Returns an iterator over a mutable reference to the right value.
            pub fn right_iter_mut(&mut self) -> EitherRightIterMut<'_, R> {
                match self {
                    Either::Left(_) => EitherRightIterMut { right: None },
                    Either::Right(r) => EitherRightIterMut { right: Some(r) },
                }
            }

            /// Maps a function over the left value by reference, leaving a right value unchanged.
            #[inline]
            pub fn fmap_left_ref<T, F>(&self, f: F) -> Either<T, R>
            where
                F: Fn(&L) -> T,
                R: Clone,
            {
                match self {
                    Either::Left(l) => Either::Left(f(l)),
                    Either::Right(r) => Either::Right(r.clone()),
                }
            }

            /// Maps a function over the right value by reference, leaving a left value unchanged.
            #[inline]
            pub fn fmap_right_ref<T, F>(&self, f: F) -> Either<L, T>
            where
                F: Fn(&R) -> T,
                L: Clone,
            {
                match self {
                    Either::Left(l) => Either::Left(l.clone()),
                    Either::Right(r) => Either::Right(f(r)),
                }
            }

            /// Bifunctor map: maps over both sides simultaneously.
            #[inline]
            pub fn bimap<L2, R2, FL, FR>(self, f_left: FL, f_right: FR) -> Either<L2, R2>
            where
                FL: FnOnce(L) -> L2,
                FR: FnOnce(R) -> R2,
            {
                match self {
                    Either::Left(l) => Either::Left(f_left(l)),
                    Either::Right(r) => Either::Right(f_right(r)),
                }
            }

            /// Bifunctor map by reference: maps over both sides simultaneously using references.
            #[inline]
            pub fn bimap_ref<L2, R2, FL, FR>(&self, f_left: FL, f_right: FR) -> Either<L2, R2>
            where
                FL: Fn(&L) -> L2,
                FR: Fn(&R) -> R2,
            {
                match self {
                    Either::Left(l) => Either::Left(f_left(l)),
                    Either::Right(r) => Either::Right(f_right(r)),
                }
            }

            /// Returns the left value or computes it from a closure.
            #[inline]
            pub fn left_or_else<F>(self, f: F) -> L
            where
                F: FnOnce(R) -> L,
            {
                match self {
                    Either::Left(l) => l,
                    Either::Right(r) => f(r),
                }
            }

            /// Returns the right value or computes it from a closure.
            #[inline]
            pub fn right_or_else<F>(self, f: F) -> R
            where
                F: FnOnce(L) -> R,
            {
                match self {
                    Either::Right(r) => r,
                    Either::Left(l) => f(l),
                }
            }

            /// Flips the Either, turning Left into Right and vice versa.
            #[inline]
            pub fn flip(self) -> Either<R, L> {
                match self {
                    Either::Left(l) => Either::Right(l),
                    Either::Right(r) => Either::Left(r),
                }
            }

            /// Returns `Some` if this is `Left` with the given value, `None` otherwise.
            #[inline]
            pub fn left_eq(&self, value: &L) -> bool
            where
                L: PartialEq,
            {
                matches!(self, Either::Left(l) if l == value)
            }

            /// Returns `Some` if this is `Right` with the given value, `None` otherwise.
            #[inline]
            pub fn right_eq(&self, value: &R) -> bool
            where
                R: PartialEq,
            {
                matches!(self, Either::Right(r) if r == value)
            }

            /// Applies a function to the contained value (if Right) or returns the default (if Left).
            #[inline]
            pub fn map_or<U, F>(self, default: U, f: F) -> U
            where
                F: FnOnce(R) -> U,
            {
                match self {
                    Either::Right(r) => f(r),
                    Either::Left(_) => default,
                }
            }

            /// Applies a function to the contained value (if Right) or computes a default (if Left).
            #[inline]
            pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
            where
                D: FnOnce(L) -> U,
                F: FnOnce(R) -> U,
            {
                match self {
                    Either::Right(r) => f(r),
                    Either::Left(l) => default(l),
                }
            }

            /// Returns the left value if present, otherwise returns the right value.
            /// This is useful for "unifying" the two types when they're the same.
            #[inline]
            pub fn into_either(self) -> Either<L, R> {
                match self {
                    Either::Left(l) => Either::Left(l),
                    Either::Right(r) => Either::Right(r),
                }
            }

            /// Converts from `&Either<L, R>` to `Either<&L, &R>`.
            #[inline]
            pub fn as_ref(&self) -> Either<&L, &R> {
                match self {
                    Either::Left(l) => Either::Left(l),
                    Either::Right(r) => Either::Right(r),
                }
            }

            /// Converts from `&mut Either<L, R>` to `Either<&mut L, &mut R>`.
            #[inline]
            pub fn as_mut(&mut self) -> Either<&mut L, &mut R> {
                match self {
                    Either::Left(l) => Either::Left(l),
                    Either::Right(r) => Either::Right(r),
                }
            }

            /// Converts from `Either<L, R>` to `Either<L2, R2>` by cloning.
            #[inline]
            pub fn cloned<L2, R2>(&self) -> Either<L2, R2>
            where
                L: Clone + Into<L2>,
                R: Clone + Into<R2>,
            {
                match self {
                    Either::Left(l) => Either::Left(l.clone().into()),
                    Either::Right(r) => Either::Right(r.clone().into()),
                }
            }

            /// Converts from `Either<&L, &R>` to `Either<L, R>` by cloning.
            #[inline]
            pub fn copied(self) -> Either<L, R>
            where
                L: Copy,
                R: Copy,
            {
                self
            }

            /// Checks if `self` is equal to `other` using a custom comparison for each side.
            #[inline]
            pub fn eq_by<L2, R2, FL, FR>(
                &self,
                other: &Either<L2, R2>,
                f_left: FL,
                f_right: FR,
            ) -> bool
            where
                FL: Fn(&L, &L2) -> bool,
                FR: Fn(&R, &R2) -> bool,
            {
                match (self, other) {
                    (Either::Left(l1), Either::Left(l2)) => f_left(l1, l2),
                    (Either::Right(r1), Either::Right(r2)) => f_right(r1, r2),
                    _ => false,
                }
            }
        }

        impl<L: Default, R> Either<L, R> {
            /// Returns the left value or the default value for `L`.
            #[inline]
            pub fn unwrap_left_or_default(self) -> L {
                match self {
                    Either::Left(l) => l,
                    Either::Right(_) => L::default(),
                }
            }
        }

        impl<L, R: Default> Either<L, R> {
            /// Returns the right value or the default value for `R`.
            #[inline]
            pub fn unwrap_right_or_default(self) -> R {
                match self {
                    Either::Right(r) => r,
                    Either::Left(_) => R::default(),
                }
            }
        }

        impl<L, R> From<Result<R, L>> for Either<L, R> {
            #[inline]
            fn from(result: Result<R, L>) -> Self {
                result_to_either(result)
            }
        }

        impl<L, R> From<Either<L, R>> for Result<R, L> {
            #[inline]
            fn from(either: Either<L, R>) -> Self {
                either_to_result(either)
            }
        }

        impl<L, R> Default for Either<L, R>
        where
            R: Default,
        {
            #[inline]
            fn default() -> Self {
                Either::Right(R::default())
            }
        }

        impl<L: std::fmt::Display, R: std::fmt::Display> std::fmt::Display for Either<L, R> {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                match self {
                    Either::Left(l) => write!(f, "Left({})", l),
                    Either::Right(r) => write!(f, "Right({})", r),
                }
            }
        }

        impl<L: std::error::Error + 'static, R: std::fmt::Debug + std::fmt::Display>
            std::error::Error for Either<L, R>
        {
            fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                match self {
                    Either::Left(l) => Some(l),
                    Either::Right(_) => None,
                }
            }
        }
    }

    // Re-export main types at crate root
    pub use either::{
        Either, EitherLeftIter, EitherLeftIterMut, EitherLeftIterRef, EitherRightIter,
        EitherRightIterMut, EitherRightIterRef,
    };
    pub use error::EitherError as Error;
    pub use functor::{Functor, FunctorExt};
    pub use hkt::{BinaryHKT, HKTType, HKT};
}
