better-py

Comparisons

Compare better-py with other functional programming libraries in Python

Comparisons

See how better-py compares to other functional programming libraries and approaches in Python.

vs Returns Library

better-py

from better_py import Some, Nothing, Ok, Error

# Maybe for optional values
value = Some(42)
result = value.map(lambda x: x * 2)

# Result for error handling
result = Ok(42)
error = Error("something went wrong")

Returns

from returns.maybe import Some, Nothing
from returns.result import Success, Failure

# Maybe for optional values
value = Some(42)
result = value.map(lambda x: x * 2)

# Result for error handling
result = Success(42)
failure = Failure("something went wrong")

Key Differences

Featurebetter-pyReturns
StyleObject-oriented with methodsFunctional + object mix
Type trackingFull generic inferenceFull generic inference
Method chainingNativeLimited
ImmutabilityFrozen dataclassesImmutable
Learning curveGentler, PythonicSteeper
PhilosophyPragmaticAcademic

Info: better-py focuses on feeling like natural Python objects, while Returns follows more traditional functional programming patterns.

vs PyMonad

better-py

from better_py import Some, Nothing

value = Some(42)
result = (
    value
    .map(lambda x: x * 2)
    .filter(lambda x: x > 50)
    .or_else(0)
)

PyMonad

from pymonad.Maybe import Just, Nothing

value = Just(42)
result = value.amap(lambda x: x * 2)
# No built-in filter, or_else, etc.

Key Differences

Featurebetter-pyPyMonad
API completenessRich, practical methodsMinimal, academic
Method chainingFull supportLimited
Modern PythonDataclasses, protocolsOlder patterns
Type hintsFull supportPartial
DocumentationComprehensiveBasic

vs Option/Maybe from Other Libraries

better-py

from better_py import Some, Nothing

def get_user(id: int) -> Some[User] | Nothing:
    if user := db.find(id):
        return Some(user)
    return Nothing()

user = get_user(1)
name = user.map(lambda u: u.name).or_else("Guest")

Optional[T]

from typing import Optional

def get_user(id: int) -> Optional[User]:
    return db.find(id)

user = get_user(1)
if user:
    name = user.name
else:
    name = "Guest"

typing-ext

from typing_ext import Option, Some, Nothing

def get_user(id: int) -> Option[User]:
    if user := db.find(id):
        return Some(user)
    return Nothing

name = get_user(1).map_or("Guest", lambda u: u.name)

Key Differences

Featurebetter-pyOptional[T]typing-ext
SafetyCompile-time + runtimeRuntime onlyRuntime only
ComposabilityExcellentPoorGood
Method chainingFullNoneGood
Type narrowingAutomaticManualLimited
Pattern matchingSupportedSupportedLimited

vs Rust's Option and Result

better-py draws inspiration from Rust's excellent error handling:

better-py

from better_py import Some, Nothing, Ok, Error

# Maybe ≈ Option
value = Some(42)
result = value.map(lambda x: x * 2).or_else(0)

# Result ≈ Result
result = Ok(42)
value = result.unwrap_or(0)

Rust

// Option
let value = Some(42);
let result = value.map(|x| x * 2).unwrap_or(0);

// Result
let result: Result<i32, &str> = Ok(42);
let value = result.unwrap_or(0);

Key Differences

Featurebetter-pyRust
Type systemGeneric type hintsAlgebraic data types
Pattern matchingif/is elif/is elsematch expressions
Compile-time checksMypy optionalBuilt-in
PerformanceOverhead of objectsZero-cost
ErgonomicsPythonic idiomsRust idioms

Info: better-py aims to bring Rust-like ergonomics to Python, while accepting the limitations of Python's type system.

Summary

Choose better-py if you want:

  • ✅ Natural Python object-oriented style
  • ✅ Excellent type safety with mypy
  • ✅ Rich, composable APIs
  • ✅ Modern Python practices (dataclasses, protocols)
  • ✅ Comprehensive documentation

Consider alternatives if you need:

  • ⚠️ Pure functional programming (use Returns)
  • ⚠️ Zero-cost abstractions (use Rust or C++)
  • ⚠️ Haskell-style patterns (use PyMonad)

Best Use Cases for better-py:

  1. New projects starting with modern Python (3.11+)
  2. Teams familiar with OOP learning FP concepts
  3. Codebases that value type safety
  4. Applications requiring robust error handling
  5. Developers who want practical FP without academic complexity

On this page