1+ from typing import Callable , Generic , TypeVar , Union
2+
3+ S = TypeVar ('S' )
4+ T = TypeVar ('T' )
5+
6+ class Monad (Generic [T ]):
7+ def __init__ (self , value , monoid ):
8+ self .value = value
9+ self .monoid = monoid
10+
11+ @classmethod
12+ def apply (cls , function ):
13+ class _Application (cls ):
14+ amap = cls .amap
15+ bind = cls .bind
16+ insert = cls .insert
17+ map = cls .map
18+ @staticmethod
19+ def to_arguments (* args ):
20+ results = cls .insert (function )
21+ for arg in args :
22+ results = result .amap (arg )
23+ return cls (result .value , result .monoid )
24+ return _Application (None , None )
25+
26+ @classmethod
27+ def insert (cls , value : T ) -> 'Monad[T]' :
28+ raise NotImplementedError
29+
30+ def amap (self : 'Monad[Callable[[S], T]]' , monad_value : 'Monad[S]' ) -> 'Monad[T]' :
31+ return monad_value .map (self .value )
32+
33+ def bind (self : 'Monad[S]' , kleisli_function : Callable [[S ], 'Monad[T]' ]) -> 'Monad[T]' :
34+ raise NotImplementedError
35+
36+ def map (self : 'Monad[S]' , function : Callable [[S ], T ]) -> 'Monad[T]' :
37+ raise NotImplementedError ("'fmap' not defined." )
38+
39+ def then (
40+ self : 'Monad[S]' , function : Union [Callable [[S ], T ], Callable [[S ], 'Monad[T]' ]]
41+ ) -> 'Monad[T]' :
42+ try :
43+ result = self .bind (function )
44+ if isinstance (result , Monad ):
45+ return result
46+ else :
47+ return self .map (function )
48+ except AttributeError :
49+ return self .map (function )
0 commit comments