小学算数1193669 views
ヒストリア282760 views
中学理科1625756 views
Computer364642 views
中学社会666920 views
いろは2981760 views
りんご189887 views
英語606840 views
中学数学621094 views
高校生物549563 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 の乱用を避け、エラー処理を宣言的に記述できます。