Coverage for src/monadc/result/result.py: 63%

1 from typing import TypeVar, Generic, Callable, Union, Any, Optional

2

3 T = TypeVar('T') # Ok type (success/value)

4 E = TypeVar('E') # Err type (error/failure)

5 U = TypeVar('U') # Generic result type

6

7 class Result(Generic[T, E]):

8 """

9 Rust-inspired Result monad for representing computations that can succeed or fail.

10

11 Result[T, E] represents a value that can be either:

12 - Ok[T]: A successful value of type T

13 - Err[E]: An error value of type E

14

15 This follows Rust conventions where Ok represents success and Err represents failure.

16 """

17

18 _UNSET = object() # Sentinel value to distinguish from None

19

20 def __new__(cls, ok_value: Any = _UNSET, err_value: Any = _UNSET) -> 'Result[T, E]':

21 """Factory constructor for Result. Prefer explicit Ok()/Err() construction."""

22 if cls is not Result:

23 # Direct subclass instantiation (Ok, Err)

24 return super().__new__(cls)

25

26 if ok_value is not cls._UNSET and err_value is not cls._UNSET:

27 raise ValueError("Cannot specify both ok_value and err_value")

28

29 if ok_value is not cls._UNSET:

30 from .ok import Ok

31 return Ok(ok_value)

32 elif err_value is not cls._UNSET:

33 from .err import Err

34 return Err(err_value)

35 else:

36 raise ValueError("Must specify either ok_value or err_value")

37

38 # Type checking methods

39 def is_ok(self) -> bool:

40 """Returns True if this Result is an Ok, False otherwise."""

41 raise NotImplementedError("Use Ok or Err, not Result directly")

42

43 def is_err(self) -> bool:

44 """Returns True if this Result is an Err, False otherwise."""

45 raise NotImplementedError("Use Ok or Err, not Result directly")

46

47 # Value extraction (Rust-style)

48 def ok(self) -> 'Any': # Returns Option[T]

49 """Get the ok value as Option - Some(value) if Ok, Nil() if Err."""

50 raise NotImplementedError("Use Ok or Err, not Result directly")

51

52 def err(self) -> 'Any': # Returns Option[E]

53 """Get the err value as Option - Some(error) if Err, Nil() if Ok."""

54 raise NotImplementedError("Use Ok or Err, not Result directly")

55

56 def unwrap(self) -> T:

57 """Get the ok value. Panics (raises exception) if this is an Err."""

58 raise NotImplementedError("Use Ok or Err, not Result directly")

59

60 def unwrap_err(self) -> E:

61 """Get the err value. Panics (raises exception) if this is an Ok."""

62 raise NotImplementedError("Use Ok or Err, not Result directly")

63

64 def unwrap_or(self, default: T) -> T:

65 """Get the ok value or return default if this is an Err."""

66 raise NotImplementedError("Use Ok or Err, not Result directly")

67

68 def unwrap_or_else(self, func: Callable[[E], T]) -> T:

69 """Get the ok value or compute default from error if this is an Err."""

70 raise NotImplementedError("Use Ok or Err, not Result directly")

71

72 # Transformations (Ok-biased)

73 def map(self, func: Callable[[T], U]) -> 'Result[U, E]':

74 """Transform the Ok value if present, otherwise return unchanged Err."""

75 raise NotImplementedError("Use Ok or Err, not Result directly")

76

77 def map_err(self, func: Callable[[E], U]) -> 'Result[T, U]':

78 """Transform the Err value if present, otherwise return unchanged Ok."""

79 raise NotImplementedError("Use Ok or Err, not Result directly")

80

81 def map_or(self, default: U, func: Callable[[T], U]) -> U:

82 """Apply func to Ok value or return default if Err."""

83 raise NotImplementedError("Use Ok or Err, not Result directly")

84

85 def map_or_else(self, default_func: Callable[[E], U], func: Callable[[T], U]) -> U:

86 """Apply func to Ok value or call default_func with Err value."""

87 raise NotImplementedError("Use Ok or Err, not Result directly")

88

89 def and_then(self, func: Callable[[T], 'Result[U, E]']) -> 'Result[U, E]':

90 """Transform Ok value to Result if present, otherwise return unchanged Err."""

91 raise NotImplementedError("Use Ok or Err, not Result directly")

92

93 def or_else(self, func: Callable[[E], 'Result[T, U]']) -> 'Result[T, U]':

94 """Transform Err value to Result if present, otherwise return unchanged Ok."""

95 raise NotImplementedError("Use Ok or Err, not Result directly")

96

97 def flatten(self) -> 'Result[Any, E]':

98 """Flatten Result[Result[T, E], E] to Result[T, E]."""

99 raise NotImplementedError("Use Ok or Err, not Result directly")

100

101 def transpose(self) -> 'Any': # Returns Option[Result[T, E]]

102 """Transpose Result[Option[T], E] to Option[Result[T, E]]."""

103 raise NotImplementedError("Use Ok or Err, not Result directly")

104

105 # Logical operations

106 def and_(self, other: 'Result[U, E]') -> 'Result[U, E]':

107 """Return other if self is Ok, otherwise return self."""

108 raise NotImplementedError("Use Ok or Err, not Result directly")

109

110 def or_(self, other: 'Result[T, U]') -> 'Result[T, U]':

111 """Return self if self is Ok, otherwise return other."""

112 raise NotImplementedError("Use Ok or Err, not Result directly")

113

114 # Inspection

115 def inspect(self, func: Callable[[T], Any]) -> 'Result[T, E]':

116 """Call func with the Ok value if present, return self unchanged."""

117 raise NotImplementedError("Use Ok or Err, not Result directly")

118

119 def inspect_err(self, func: Callable[[E], Any]) -> 'Result[T, E]':

120 """Call func with the Err value if present, return self unchanged."""

121 raise NotImplementedError("Use Ok or Err, not Result directly")

122

123 # Conversions

124 def to_option(self) -> 'Any': # Returns Option[T]

125 """Convert Result to Option, losing error information."""

126 raise NotImplementedError("Use Ok or Err, not Result directly")

127

128 def to_try(self) -> 'Any': # Returns Try[T]

129 """Convert Result to Try, converting Err to Failure."""

130 raise NotImplementedError("Use Ok or Err, not Result directly")