1
1
# -*- coding: utf-8 -*-
2
2
3
- from abc import ABCMeta , abstractmethod
4
- from typing import Any , Callable , Generic , NoReturn , TypeVar , Union
5
-
6
- from typing_extensions import final
3
+ from abc import ABCMeta
7
4
8
5
from returns .primitives .exceptions import UnwrapFailedError
9
- from returns .primitives .monad import Monad , NewValueType , ValueType
10
- from returns .primitives .types import MonadType
11
-
12
- _ErrorType = TypeVar ('_ErrorType' )
13
-
14
-
15
- # That's the most ugly part.
16
- # We need to express `Either` with two type parameters and
17
- # Left and Right with just one parameter.
18
- # And that's how we do it. Any other and more cleaner ways are appreciated.
19
- class Either (Generic [ValueType , _ErrorType ], metaclass = ABCMeta ):
20
- """
21
- Represents a calculation that may either fail or succeed.
6
+ from returns .primitives .monad import Monad
22
7
23
- An alternative to using exceptions.
24
- 'Either' (or its alias 'Result') is an abstract type and should not
25
- be instantiated directly. Instead use 'Right' (or its alias 'Success')
26
- and 'Left' (or its alias 'Failure').
27
- """
28
-
29
- _inner_value : Union [ValueType , _ErrorType ]
30
-
31
- @abstractmethod
32
- def unwrap (self ) -> ValueType : # pragma: no cover
33
- """
34
- Custom magic method to unwrap inner value from monad.
35
8
36
- Should be redefined for ones that actually have values.
37
- And for ones that raise an exception for no values.
38
- """
39
- raise NotImplementedError ()
9
+ class Either (Monad , metaclass = ABCMeta ):
10
+ """Base class for Left and Right."""
40
11
41
12
42
- @final
43
- class Left (Either [Any , _ErrorType ], Monad [_ErrorType ]):
13
+ class Left (Either ):
44
14
"""
45
15
Represents a calculation which has failed.
46
16
47
17
It should contain an error code or message.
48
18
To help with readability you may alternatively use the alias 'Failure'.
49
19
"""
50
20
51
- def __init__ (self , inner_value : _ErrorType ) -> None :
52
- """
53
- Wraps the given value in the Container.
54
-
55
- 'value' is any arbitrary value of any type including functions.
56
- """
57
- object .__setattr__ (self , '_inner_value' , inner_value )
58
-
59
- def fmap (self , function ) -> 'Left[_ErrorType]' :
21
+ def fmap (self , function ):
60
22
"""Returns the 'Left' instance that was used to call the method."""
61
23
return self
62
24
63
- def bind (self , function ) -> 'Left[_ErrorType]' :
25
+ def bind (self , function ):
64
26
"""Returns the 'Left' instance that was used to call the method."""
65
27
return self
66
28
67
- def efmap (
68
- self ,
69
- function : Callable [[_ErrorType ], NewValueType ],
70
- ) -> 'Right[NewValueType]' :
29
+ def efmap (self , function ):
71
30
"""
72
31
Applies function to the inner value.
73
32
@@ -78,7 +37,7 @@ def efmap(
78
37
"""
79
38
return Right (function (self ._inner_value ))
80
39
81
- def ebind (self , function : Callable [[ _ErrorType ], MonadType ]) -> MonadType :
40
+ def ebind (self , function ) :
82
41
"""
83
42
Applies 'function' to the result of a previous calculation.
84
43
@@ -87,39 +46,27 @@ def ebind(self, function: Callable[[_ErrorType], MonadType]) -> MonadType:
87
46
"""
88
47
return function (self ._inner_value )
89
48
90
- def value_or (self , default_value : NewValueType ) -> NewValueType :
49
+ def value_or (self , default_value ) :
91
50
"""Returns the value if we deal with 'Right' or default if 'Left'."""
92
51
return default_value
93
52
94
- def unwrap (self ) -> NoReturn :
53
+ def unwrap (self ):
95
54
"""Raises an exception, since it does not have a value inside."""
96
55
raise UnwrapFailedError (self )
97
56
98
- def failure (self ) -> _ErrorType :
57
+ def failure (self ):
99
58
"""Unwraps inner error value from failed monad."""
100
59
return self ._inner_value
101
60
102
61
103
- @final
104
- class Right (Either [ValueType , Any ], Monad [ValueType ]):
62
+ class Right (Either ):
105
63
"""
106
64
Represents a calculation which has succeeded and contains the result.
107
65
108
66
To help with readability you may alternatively use the alias 'Success'.
109
67
"""
110
68
111
- def __init__ (self , inner_value : ValueType ) -> None :
112
- """
113
- Wraps the given value in the Container.
114
-
115
- 'value' is any arbitrary value of any type including functions.
116
- """
117
- object .__setattr__ (self , '_inner_value' , inner_value )
118
-
119
- def fmap (
120
- self ,
121
- function : Callable [[ValueType ], NewValueType ],
122
- ) -> 'Right[NewValueType]' :
69
+ def fmap (self , function ):
123
70
"""
124
71
Applies function to the inner value.
125
72
@@ -130,10 +77,7 @@ def fmap(
130
77
"""
131
78
return Right (function (self ._inner_value ))
132
79
133
- def bind (
134
- self ,
135
- function : Callable [[ValueType ], MonadType ],
136
- ) -> MonadType :
80
+ def bind (self , function ):
137
81
"""
138
82
Applies 'function' to the result of a previous calculation.
139
83
@@ -142,23 +86,23 @@ def bind(
142
86
"""
143
87
return function (self ._inner_value )
144
88
145
- def efmap (self , function ) -> 'Right[ValueType]' :
89
+ def efmap (self , function ):
146
90
"""Returns the 'Right' instance that was used to call the method."""
147
91
return self
148
92
149
- def ebind (self , function ) -> 'Right[ValueType]' :
93
+ def ebind (self , function ):
150
94
"""Returns the 'Right' instance that was used to call the method."""
151
95
return self
152
96
153
- def value_or (self , default_value : NewValueType ) -> ValueType :
97
+ def value_or (self , default_value ) :
154
98
"""Returns the value if we deal with 'Right' or default if 'Left'."""
155
99
return self ._inner_value
156
100
157
- def unwrap (self ) -> ValueType :
101
+ def unwrap (self ):
158
102
"""Returns the unwrapped value from the inside of this monad."""
159
103
return self ._inner_value
160
104
161
- def failure (self ) -> NoReturn :
105
+ def failure (self ):
162
106
"""Raises an exception, since it does not have an error inside."""
163
107
raise UnwrapFailedError (self )
164
108
0 commit comments