Last active
December 14, 2022 13:46
-
-
Save noamraph/35ef0114fb667322367b5d75a0c254d1 to your computer and use it in GitHub Desktop.
Understanding the Haskell IO monad by implementing it in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Based on https://youtu.be/fCoQb-zqYDI | |
# This passes `mypy --strict`, which is cool. | |
from __future__ import annotations | |
from typing import NamedTuple, Tuple, Callable, TypeVar | |
A = TypeVar('A') | |
B = TypeVar('B') | |
class World(NamedTuple): | |
pass | |
def print_str(s: str, w: World) -> World: | |
print(s) | |
return w | |
def read_str(w: World) -> Tuple[str, World]: | |
s = input() | |
return s, w | |
WorldT = Callable[[World], Tuple[A, World]] | |
def bind(wt: WorldT[A], f: Callable[[A], WorldT[B]]) -> WorldT[B]: | |
def wt_r(w: World) -> Tuple[B, World]: | |
t, w2 = wt(w) | |
wt2 = f(t) | |
s, w3 = wt2(w2) | |
return s, w3 | |
return wt_r | |
def read_str_t(w: World) -> Tuple[str, World]: | |
s, w = read_str(w) | |
return s, w | |
_verify_read_str_t_type: WorldT[str] = read_str_t | |
def print_str_t(s: str) -> WorldT[None]: | |
def wt(w: World) -> Tuple[None, World]: | |
w2 = print_str(s, w) | |
return None, w2 | |
return wt | |
def what_is_your_pure_name(w1: World) -> World: | |
w2 = print_str("What is your name?", w1) | |
name, w3 = read_str(w2) | |
w4 = print_str(f"Hello, {name}", w3) | |
return w4 | |
what_is_your_pure_name_t: WorldT[None] = bind( | |
print_str_t("What is your name?"), | |
lambda _: bind(read_str_t, lambda name: print_str_t(f"Hi, {name}"))) | |
conditional_t: WorldT[None] = bind( | |
print_str_t("What is your name?"), | |
lambda _: bind( | |
read_str_t, lambda name: bind( | |
print_str_t("That's a nice name!") if name == 'noam' else print_str_t("That's a name."), | |
lambda _: print_str_t("Ok, I'm done.") | |
) | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment