Advertisement
banovski

Option type monad in Python?

Aug 1st, 2024 (edited)
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.58 KB | Source Code | 0 0
  1. #! /usr/bin/env python3
  2.  
  3. """An optional type monad."""
  4.  
  5. class Option:
  6.     """Optional type."""
  7.     def __init__(self, contains, *value):
  8.         if contains:
  9.             self.value = value[0]
  10.             self.contains = True
  11.         else:
  12.             self.value = None
  13.             self.contains = False
  14.  
  15.     def __repr__(self):
  16.         return str((self.contains, self.value))
  17.  
  18.     def __eq__(self, arg):
  19.         return self.value == arg.value
  20.  
  21. def bind(value: Option, function):
  22.     """A function more or less equivalent to the 'bind' operator in
  23. Haskell that is used for building function chains for processing
  24. optional monadic values"""
  25.     if value.contains:
  26.         return function(value.value)
  27.     return value
  28.  
  29. def increment(value):
  30.     """Incretment a value and wrap it in the optional value."""
  31.     return Option(True, value + 1)
  32.  
  33. def fuck_up_chain(value):
  34.     """Emulate failure."""
  35.     return Option(False, None)
  36.  
  37. OUTPUT_TEXT = [
  38.     "1. An empty optional value:",
  39.     Option(False),
  40.     "2. A non-empty optional value:",
  41.     Option(True, 7),
  42.     "3. Applying the 'bind' to the empty optional value and the increment function:",
  43.     "bind(Option(False), increment) →",
  44.     bind(Option(False), increment),
  45.     "4. Applying the 'bind' to the non-empty optional value and the increment function:",
  46.     "bind(Option(True, 7), increment) →",
  47.     bind(Option(True, 7), increment),
  48.     "5. Nested (chained) 'bind' application:",
  49.     "bind(bind(Option(True, 7), increment), increment) →",
  50.     bind(bind(Option(True, 7), increment), increment),
  51.     "6. Introducing failure to the chain:",
  52.     "bind(bind(bind(Option(True, 7), increment), fuck_up_chain), increment) →",
  53.     bind(bind(bind(Option(True, 7), increment), fuck_up_chain), increment),
  54.     "7. The first monadic law: return a >>= h ≡ h a",
  55.     "bind(Option(True, 7), increment) == increment(7) →",
  56.     bind(Option(True, 7), increment) == increment(7),
  57.     "8. The second monadic law: m >>= return ≡ m",
  58.     "bind(Option(True, 7), (lambda x: Option(True, x))) == Option(True, 7) →",
  59.     bind(Option(True, 7), (lambda x: Option(True, x))) == Option(True, 7),
  60.     "9. The third monadic law: \
  61. (m >>= g) >>= h ≡ m >>= (\\x -> g x >>= h)",
  62.     "bind(bind(Option(True, 7), increment), increment) == \
  63. bind(Option(True, 7), (lambda x: bind(increment(x), increment))) →",
  64.     bind(bind(Option(True, 7), increment), increment) == \
  65.     bind(Option(True, 7), (lambda x: bind(increment(x), increment)))
  66. ]
  67.  
  68. for line in OUTPUT_TEXT:
  69.     print(line)
  70.  
  71. # 1. An empty optional value:
  72. # (False, None)
  73. # 2. A non-empty optional value:
  74. # (True, 7)
  75. # 3. Applying the 'bind' to the empty optional value and the increment function:
  76. # bind(Option(False), increment) →
  77. # (False, None)
  78. # 4. Applying the 'bind' to the non-empty optional value and the increment function:
  79. # bind(Option(True, 7), increment) →
  80. # (True, 8)
  81. # 5. Nested (chained) 'bind' application:
  82. # bind(bind(Option(True, 7), increment), increment) →
  83. # (True, 9)
  84. # 6. Introducing failure to the chain:
  85. # bind(bind(bind(Option(True, 7), increment), fuck_up_chain), increment) →
  86. # (False, None)
  87. # 7. The first monadic law: return a >>= h ≡ h a
  88. # bind(Option(True, 7), increment) == increment(7) →
  89. # True
  90. # 8. The second monadic law: m >>= return ≡ m
  91. # bind(Option(True, 7), (lambda x: Option(True, x))) == Option(True, 7) →
  92. # True
  93. # 9. The third monadic law: (m >>= g) >>= h ≡ m >>= (\x -> g x >>= h)
  94. # bind(bind(Option(True, 7), increment), increment) == bind(Option(True, 7), (lambda x: bind(increment(x), increment))) →
  95. # True
  96.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement