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

62 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-08-19 20:24 -0700

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

2 

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

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

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

6 

7class 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")