Computer365519 views
いろは2989323 views
高校化学2914333 views
ヒストリア284772 views
教育148971 views
中学数学621615 views
中学社会667260 views
高校倫理1434006 views
高校日本史189930 views
英語608578 views
Help
Tools

English

Python でモナド的パターンの実装(Maybe, Either)

関数型プログラミングの Maybe(Option)と Either(Result)パターンを Python で実装すると、エラー処理を型安全かつ合成可能にできます。

Maybe パターン

値が存在するかしないかを表現します。

from typing import TypeVar, Generic, Callable, Optional
from dataclasses import dataclass

T = TypeVar("T")
U = TypeVar("U")

class Maybe(Generic[T]):
    pass

@dataclass
class Just(Maybe[T]):
    value: T

@dataclass
class Nothing(Maybe[T]):
    pass

def map_maybe(m: Maybe[T], f: Callable[[T], U]) -> Maybe[U]:
    if isinstance(m, Just):
        return Just(f(m.value))
    return Nothing()

def bind_maybe(m: Maybe[T], f: Callable[[T], Maybe[U]]) -> Maybe[U]:
    if isinstance(m, Just):
        return f(m.value)
    return Nothing()

使用例:

def safe_div(a: int, b: int) -> Maybe[float]:
    if b == 0:
        return Nothing()
    return Just(a / b)

result = bind_maybe(Just(10), lambda x: safe_div(x, 2))
# Just(value=5.0)

Either パターン

成功と失敗の両方に値を持てます。

from typing import TypeVar, Generic, Callable, Union
from dataclasses import dataclass

L = TypeVar("L")  # Left(エラー)
R = TypeVar("R")  # Right(成功)

class Either(Generic[L, R]):
    pass

@dataclass
class Left(Either[L, R]):
    value: L

@dataclass
class Right(Either[L, R]):
    value: R

def map_either(e: Either[L, R], f: Callable[[R], U]) -> Either[L, U]:
    if isinstance(e, Right):
        return Right(f(e.value))
    return e

def bind_either(
    e: Either[L, R], f: Callable[[R], Either[L, U]]
) -> Either[L, U]:
    if isinstance(e, Right):
        return f(e.value)
    return e

使用例:

def parse_int(s: str) -> Either[str, int]:
    try:
        return Right(int(s))
    except ValueError:
        return Left(f"Cannot parse '{s}'")

result = bind_either(
    parse_int("42"),
    lambda x: Right(x * 2) if x > 0 else Left("Must be positive")
)
# Right(value=84)

これらのパターンにより、None チェックの連鎖や try-except の乱用を避け、エラー処理を宣言的に記述できます。