Skip to content

Io

IO dataclass

Bases: Generic[A]

summary

Parameters:

Name Type Description Default
Generic _type_

description

required

Returns:

Name Type Description
_type_

description

Source code in funclift/types/io.py
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
@dataclass
# class IO(Monad[A]):
class IO(Generic[A]):
    """_summary_

    Args:
        Generic (_type_): _description_

    Returns:
        _type_: _description_
    """

    unsafe_run: Callable[[], A]

    @staticmethod
    def raise_error(or_else: Callable[[], Exception]) -> IO[Exception]:
        return IO.pure(or_else())

    # def handle_error(self): ...

    @staticmethod
    def from_option(option: Option[A],
                    or_else: Callable[[], Exception]) -> IO[A] | IO[Exception]:
        match option:
            case Some(v):
                return IO.pure(v)
            case Nothing():
                return IO.raise_error(or_else)
            case _:
                return IO.raise_error(or_else)

        # value = option.get()
        # if (value == None):
        #     return IO.raise_error(or_else)
        # else:
        #     return IO.pure(value)

    @staticmethod
    def pure(a: B) -> IO[B]:
        return IO(lambda: a)
        # if callable(a):
        #     return IO(a)
        # else:
        #     return IO(lambda: a)

    def fmap(self, f: Callable[[A], B]) -> IO[B]:
        return IO(lambda: f(self.unsafe_run()))

    def flatmap(self, f: Callable[[A], IO[B]]) -> IO[B]:
        # Should not do this because it executes self.unsafe_run() right away.
        # return f(self.unsafe_run())
        def foo():
            a: A = self.unsafe_run()
            fa: IO[B] = f(a)
            return fa.unsafe_run()
        return IO(foo)

    def ap(self, a: IO[D]) -> IO[E]:
        return a.fmap(lambda x: cast(Callable[[D], E], self.unsafe_run())(x))