Introduction
Monads are a functional programming pattern that provides a way to handle computations with context. Python can implement common monads like Maybe, Either, and Option.
Maybe Monad (Optional)
from typing import TypeVar, Generic, Callable
T = TypeVar("T")
U = TypeVar("U")
class Maybe(Generic[T]):
def __init__(self, value):
self._value = value
self._is_just = value is not None
@staticmethod
def just(value):
return Maybe(value)
@staticmethod
def nothing():
return Maybe(None)
def bind(self, func: Callable[[T], "Maybe[U]"]) -> "Maybe[U]":
if self._is_just:
return func(self._value)
return Maybe.nothing()
def get_or_else(self, default):
return self._value if self._is_just else default
def safe_divide(a, b):
if b == 0:
return Maybe.nothing()
return Maybe.just(a / b)
result = Maybe.just(10).bind(lambda x: safe_divide(x, 2))
print(result.get_or_else(0)) # 5.0
Either Monad
class Either(Generic[T, U]):
def __init__(self, value, is_right=True):
self._value = value
self._is_right = is_right
@staticmethod
def right(value):
return Either(value, True)
@staticmethod
def left(value):
return Either(value, False)
def bind(self, func):
if self._is_right:
return func(self._value)
return self
def get_right(self):
return self._value if self._is_right else None
def divide(a, b):
if b == 0:
return Either.left("Division by zero")
return Either.right(a / b)
result = Either.right(10).bind(lambda x: divide(x, 2))
print(result.get_right()) # 5.0
Option Type Pattern
from typing import Optional
def find_user(id: int) -> Optional[dict]:
if id in users:
return users[id]
return None
def get_email(user: dict) -> Optional[str]:
return user.get("email")
# Using Optional chaining pattern
email = (find_user(1)
.map(get_email)
.or_else("no email"))
Result Monad
from dataclasses import dataclass
@dataclass
class Result:
value: any
error: str = None
@staticmethod
def success(value):
return Result(value, None)
@staticmethod
def failure(error):
return Result(None, error)
def bind(self, func):
if self.error:
return self
return func(self.value)
Practice Problems
- Implement Maybe monad with map
- Create Either for error handling
- Implement Result pattern for operations
- Build Option type with flatmap
- Chain multiple monadic operations