Coverage for greyhorse / river / private / monads / reader.py: 100%
18 statements
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-18 11:33 +0300
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-18 11:33 +0300
1from __future__ import annotations
3from collections.abc import Callable
6class Reader[R, T]:
7 """Reader monad — computation that depends on an environment.
9 Wraps a function ``R -> T``. Call with an environment to get the result.
11 Type parameters:
12 R: Environment (reader context) type.
13 T: Result type.
15 Examples:
16 ::
18 r = Reader(lambda x: x + 1)
19 assert r(10) == 11
21 doubled = r.map(lambda v: v * 2)
22 assert doubled(10) == 22
24 chained = r.and_then(lambda v: Reader(lambda r: v * r))
25 assert chained(5) == 30 # (5+1) * 5
26 """
28 __slots__ = ('_run',)
30 def __init__(self, function: Callable[[R], T]) -> None:
31 self._run = function
33 def map[U](self, f: Callable[[T], U]) -> Reader[R, U]:
34 """Apply a pure function to the result."""
35 def run(r: R) -> U:
36 a = self._run(r)
37 return f(a)
39 return Reader(run)
41 def and_then[U](self, f: Callable[[T], Reader[R, U]]) -> Reader[R, U]:
42 """Monadic bind — chain with a function returning Reader."""
43 def run(r: R) -> U:
44 a = self._run(r)
45 return f(a)(r)
47 return Reader(run)
49 def __call__(self, r: R) -> T:
50 """Execute the computation with the given environment."""
51 return self._run(r)