diff --git a/perhaps/maybe.py b/perhaps/maybe.py index 9785cd3..aae3aab 100644 --- a/perhaps/maybe.py +++ b/perhaps/maybe.py @@ -107,6 +107,22 @@ def unwrap_or_else(self, f: Callable[[], T]) -> T: """ ... + @abstractmethod + def filter(self, f: Callable[[T], bool]) -> "Maybe[T]": + """ + Filter the value of the Maybe, returning Nothing if the predicate returns False. + + Analogous to `Option::filter` in Rust. + + >>> Just(1).filter(lambda x: x > 1) + Nothing() + >>> Just(1).filter(lambda x: x < 1) + Nothing() + >>> Just(1).filter(lambda x: x == 1) + Just(1) + """ + ... + @abstractmethod def to_optional(self) -> Optional[T]: """ @@ -201,6 +217,9 @@ def unwrap_or(self, default: T) -> T: def unwrap_or_else(self, f: Callable[[], T]) -> T: return self.value + def filter(self, f: Callable[[T], bool]) -> Maybe[T]: + return self if f(self.value) else Nothing() + def to_optional(self) -> T: return self.value @@ -276,6 +295,9 @@ def unwrap_or(self, default: T) -> T: def unwrap_or_else(self, f: Callable[[], T]) -> T: return f() + def filter(self, f: Callable[[T], bool]) -> "Nothing[T]": + return Nothing() + def to_optional(self) -> None: return None diff --git a/tests/test_maybe.py b/tests/test_maybe.py index f24264d..d12b4aa 100644 --- a/tests/test_maybe.py +++ b/tests/test_maybe.py @@ -71,6 +71,12 @@ def test_unwrap_or(): assert Nothing().unwrap_or(2) == 2 +def test_filter(): + assert Just(1).filter(lambda x: x > 1) == Nothing() + assert Just(1).filter(lambda x: x < 1) == Nothing() + assert Just(1).filter(lambda x: x == 1) == Just(1) + + def test_from_try(): assert Maybe.from_try(lambda: 1 / 1, ZeroDivisionError) == Just(1) assert Maybe.from_try(lambda: 1 / 0, ZeroDivisionError) == Nothing()