
Btw, just to give some context: The reason we need sentinels at all is because our APIs don't like to wrap the happy case. As an example: So in Python, when you do {'a': 'foo'}.get('a') you get 'foo' directly. That's convenient. In eg Haskell the equivalent operation gives you a wrapped 'foo'. ghci> :m + Data.Map ghci> Data.Map.lookup "a" (Data.Map.fromList [("a", "foo")]) Just "foo" The benefit is that you can tell these two cases apart: ghci> Data.Map.lookup "b" (Data.Map.fromList [("c", Nothing)]) Nothing ghci> Data.Map.lookup "c" (Data.Map.fromList [("c", Nothing)]) Just Nothing The drawback is that you have to unwrap your happy case (you have to remove the `Just`.) Many Python functions side-step the need for a sentinel by using exceptions: the result of {'some-key': None}['some-key'] is unambigous, but needs exception handling. Using common sentinels would be totally besides the point: what if you want to stick these common sentinels in eg a dict (or any other structure whose operations sometimes use sentinels)?