Rust-style Monad utils for Python
Project description
RustyMonad
Rust-Style Monad Utilities for Python
Getting Started
Introduction
RustyMonad is a Python package designed to incorporate a Rust-style exception handling mechanisms into Python programming. This approach not only simplifies code and also enhances its readability and maintainability.
Features
- Rust-style Exception Handling: Based on Monad's
Option
andResult
modules, it provides a mechanism similar to Rust's exception handling - Do-Notation Syntax Sugar: Supports decorators to simplify monadic operations
- Match-Case Statement Support: Supports pattern matching using match-case statements
- Complete Type Annotations: Includes full type annotations and supports generics (use
mypy
for type checking) - No External Dependencies: The package does not rely on external dependencies, making it lightweight and easy to integrate
Installation
RustyMonad is available on PyPI:
python -m pip install RustyMonad
For optimal user experience, it is recommended to use Python 3.10 or higher to support the use of match-case
statements.
Usage Example
from rustymonad import Result, Ok, Err, DoRet, do_notation
def safe_div(x: float, y: float) -> Result[float, str]:
if y == 0:
return Err('division by zero')
return Ok(x / y)
def safe_sqrt(x: float) -> Result[float, str]:
if x < 0:
return Err('square root of a negative number')
return Ok(math.sqrt(x))
@do_notation
def calc_process(a: float, b: float) -> DoRet[Result[float, str]]:
root = yield safe_sqrt(a)
quotient = yield safe_div(root, b)
return Ok(quotient)
assert calc_process(9, 2) == Ok(1.5)
assert calc_process(9, 0) == Err('division by zero')
match calc_process(9, 2):
case Ok(result):
print(f'call calc_process() successful. {result = }')
case Err(error):
print(f'call calc_process() failed. {error = }')
More Examples
Option
Option[T]
is used to represent an optional(nullable) value, typically used for type declarations. Option[T]
can either contain a value Some(T)
or be empty Nothing()
. This can replace the Optional
type from the typing
module. Nothing
behaves similarly to None
but supports branch selection or null value handling through interfaces to avoid using numerous if
statements for null checks.
Handling null values with Option
:
from rustymonad import Option, Some, Nothing
def safe_div(x: float, y: float) -> Option[float]:
if y == 0:
return Nothing()
return Some(x / y)
other_method(safe_div(1, 0).unwrap_or(0))
match safe_div(1, 2):
case Some(x):
print(f'result is {x}')
case Nothing(): # Also use `case _:` for the last case statement
print('cannot divide by 0')
Result
Result[T, E]
is commonly used to represent the result of an operation or any exceptions generated during the operation. It is generally used for type declarations. Result[T, E]
can either contain a success value Ok(T)
or an error Err(E)
.
Handling exceptions with Result
:
from rustymonad import Result, Ok, Err
def safe_div(x: float, y: float) -> Result[float, Exception]:
try:
return Ok(x / y)
except Exception as e:
return Err(e)
value = (
safe_div(1, 2)
.and_then(lambda x: Ok(x * x))
.or_else(lambda e: Ok(0))
.inspect(print)
.unwrap()
)
match safe_div(10, 2).and_then(lambda x: Ok(int(x))):
case Ok(v) if v % 2 == 1:
print(f'result is a odd')
case Ok(_):
print('result is a even')
case Err(e):
print(f'something wrong with {e}')
License
This project is licensed under the MIT License - see the LICENSE file for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for RustyMonad-1.0.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2ded5f7ab84d4f0e4fa5c6d1542ce9dc82b66b845a12d2b17411784fcea9017c |
|
MD5 | 0ec621f44b6ce48077d5e6f6bb8d2a56 |
|
BLAKE2b-256 | 2f093062f90b0cb39b7aa012766fda56bbae0e0b014f5b803d51dd806979358e |