-
Notifications
You must be signed in to change notification settings - Fork 6
/
Option.py
106 lines (76 loc) · 2.4 KB
/
Option.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# -*- coding: utf-8 -*-
"""
pyeffects.Option
~~~~~~~~~~~~----
This module implements the Option, Some, and Empty classes.
"""
from typing import Callable, TypeVar
from .Monad import Monad
A = TypeVar('A', covariant=True)
B = TypeVar('B')
class Option(Monad[A]):
@staticmethod
def of(value: B) -> 'Option[B]':
"""Constructs a :class:`Option <Option>`.
:param value: value of the new :class:`Option` object.
:rtype: pyEffects.Option
Usage::
>>> from pyeffects.Option import *
>>> Option.of(5)
Some(5)
>>> Option.of("abc")
Some(abc)
>>> Option.of(None)
Empty()
"""
return empty if value is None else Some(value)
def flat_map(self, func: Callable[[A], 'Monad[B]']) -> 'Monad[B]':
"""Flatmaps a function for :class:`Option <Option>`.
:param func: function returning a pyEffects.Option to apply to flat_map.
:rtype: pyEffects.Option
Usage::
>>> from pyeffects.Option import *
>>> Some(5).flat_map(lambda v: Some(v * v))
Some(25)
"""
if not hasattr(func, "__call__"):
raise TypeError("Option.flat_map expects a callable")
if self.is_defined():
return func(self.value)
else:
return empty
def is_defined(self) -> bool:
"""Returns if the :class:`Option <Option>` is defined or not.
:rtype: bool
Usage::
>>> from pyeffects.Option import *
>>> Some(5).is_defined()
True
"""
return self.biased
def is_empty(self) -> bool:
"""Returns if the :class:`Option <Option>` is empty or not.
:rtype: bool
Usage::
>>> from pyeffects.Option import *
>>> Some(5).is_empty()
False
"""
return not self.is_defined()
class Some(Option[A]):
def __init__(self, value: A) -> None:
self.value = value
self.biased = True
def __str__(self) -> str:
return 'Some(' + str(self.value) + ')'
def __repr__(self) -> str:
return self.__str__()
class Empty(Option[A]):
def __init__(self) -> None:
self.value = None # type: ignore
self.biased = False
def __str__(self) -> str:
return 'Empty()'
def __repr__(self) -> str:
return self.__str__()
empty = Empty() # type: ignore