// Option type utilities
// For working with optional values

/// Wrap a value in Some
pub fn some<T>(value: T): Option<T> = Some(value)

/// The None value
pub fn none<T>(): Option<T> = None

/// Check if option has a value
pub fn isSome<T>(opt: Option<T>): Bool =
    match opt {
        Some(_) => true,
        None => false
    }

/// Check if option is empty
pub fn isNone<T>(opt: Option<T>): Bool =
    match opt {
        Some(_) => false,
        None => true
    }

/// Get value or default
pub fn unwrapOr<T>(opt: Option<T>, default: T): T =
    match opt {
        Some(v) => v,
        None => default
    }

/// Map over the value if present
pub fn map<T, U>(opt: Option<T>, f: fn(T): U): Option<U> =
    match opt {
        Some(v) => Some(f(v)),
        None => None
    }

/// FlatMap (bind) for options
pub fn flatMap<T, U>(opt: Option<T>, f: fn(T): Option<U>): Option<U> =
    match opt {
        Some(v) => f(v),
        None => None
    }

/// Filter option by predicate
pub fn filter<T>(opt: Option<T>, pred: fn(T): Bool): Option<T> =
    match opt {
        Some(v) => if pred(v) then Some(v) else None,
        None => None
    }

/// Convert Option to List (empty or singleton)
pub fn toList<T>(opt: Option<T>): List<T> =
    match opt {
        Some(v) => [v],
        None => []
    }
