diff --git a/monads/maybe.py b/monads/maybe.py index 64b80a1..691c77a 100644 --- a/monads/maybe.py +++ b/monads/maybe.py @@ -65,6 +65,19 @@ class Maybe(Monad[T]): else: return result.Err(error) + @classmethod + def fromOptional(cls, value: Optional[T]) -> Maybe[T]: + if value is None: + return Nothing() + else: + return Just(value) + + def toOptional(self) -> Optional[T]: + if isinstance(self, Just): + return self.value + else: + return None + @classmethod def fromList(self, xs: List[T]) -> Maybe[T]: if xs: diff --git a/monads/result.py b/monads/result.py index 7d1fbce..ee72e49 100644 --- a/monads/result.py +++ b/monads/result.py @@ -1,6 +1,6 @@ from __future__ import annotations import functools -from typing import Any, Callable, Generic, Iterable, List, TypeVar +from typing import Any, Callable, Generic, Iterable, List, Optional, TypeVar from . import maybe from .monad import Monad @@ -76,6 +76,19 @@ class Result(Monad[T], Generic[T, E]): def toMaybe(self) -> maybe.Maybe[T]: return self.map(maybe.Maybe.pure).withDefault(maybe.Nothing()) + @classmethod + def fromOptional(cls, value: Optional[T], error: E) -> Result[T, E]: + if value is None: + return Err(error) + else: + return Ok(value) + + def toOptional(self) -> Optional[T]: + if isinstance(self, Ok): + return self.value + else: + return None + __rshift__ = bind __and__ = lambda other, self: Result.apply(self, other) __mul__ = __rmul__ = map diff --git a/tests/test_maybe.py b/tests/test_maybe.py index fc5072a..1d3140b 100644 --- a/tests/test_maybe.py +++ b/tests/test_maybe.py @@ -110,3 +110,19 @@ def test_just_to_result() -> None: def test_nothing_to_result() -> None: assert Err("oops") == Nothing().toResult("oops") + + +def test_from_optional_value() -> None: + assert Just(2) == Maybe.fromOptional(2) + + +def test_from_optional_none() -> None: + assert Nothing() == Maybe.fromOptional(None) + + +def test_just_to_optional() -> None: + assert 2 == Just(2).toOptional() + + +def test_nothing_to_optional() -> None: + assert None == Nothing().toOptional() diff --git a/tests/test_result.py b/tests/test_result.py index f1b33a7..9741cf6 100644 --- a/tests/test_result.py +++ b/tests/test_result.py @@ -165,3 +165,19 @@ def test_ok_to_maybe() -> None: def test_err_to_maybe() -> None: result: Result[int, str] = Err("error") assert Nothing() == result.toMaybe() + + +def test_from_optional_value() -> None: + assert Just(2) == Maybe.fromOptional(2) + + +def test_from_optional_none() -> None: + assert Err("error") == Result.fromOptional(None, "error") + + +def test_ok_to_optional() -> None: + assert 2 == Ok(2).toOptional() + + +def test_err_to_optional() -> None: + assert None == Err("error").toOptional()