Hacker News new | past | comments | ask | show | jobs | submit login

I wholefully agree, the problem with this kind of repos is that Python already makes most patterns trivial. So you either create a trivial example that does not bring value or you introduce unnecessary abstractions for the sake of them. I am always looking into these repos though because I am still interested in learning new Python tricks. One of the repos that I found interesting recently is https://github.com/dry-python/returns



I like the Maybe part, everything else feels like hitting my head against a wall, every time I try to understand it.

But that's likely a me problem, I assume that for people more familiar with monads and all that jazz, it's easier to understand.


All these lambdas seem excessive. "Maybe"-like pattern in Python can look like (None is falsy and custom objects are true):

  # note: `None and f()` returns None without calling f
  balance = user and user.get_balance()
  credit = balance and balance.credit_amount()
  discount_program = choose_discount(credit) if credit and credit > 0 else None
https://stackoverflow.com/questions/8507200/maybe-kind-of-mo...


Nullable (Optional[Foo] / Union[Foo, None]) and Maybe[Foo] are similar but not quite the same thing. The difference is quite subtle.

Optional[Foo] is same as Foo | None, meaning you can operate on foo with Foo's methods, except that if it's None, you get NoneType errors.

Maybe[Foo] is an actual container. You have to map over or unwrap it to operate on Foo.

The big difference is ergonomics/opinion. You can't actually map over Optional, so every time you wanna use it, you have to manually check if foo is not None. Whereas Maybe, you can operate generically over it. Some folks think "is not None" is better. Personally I hate NoneType errors in prod and find that much more painful than a bit of indirection.


It looks like a distinction without a difference. We can consider `None and f()` pattern as explicit syntax that unwraps objects as necessary without infecting other code.

Background: an object that either None or true in a boolean context (true unless overriden for custom objects). Given such object, we can consider it in a virtual Maybe container/box. When we want to use it, we have to unwrap it using `obj and obj.method()` syntax. Then `obj.method()` is ordinary "unwrapped" call.

Just to remind you. Here's how "ergonomic" Maybe variant from the article look like:

  # Type hint here is optional, it only helps the reader here:
  discount_program: Maybe['DiscountProgram'] = Maybe.from_optional(
      user,
  ).bind_optional(  # This won't be called if `user is None`
      lambda real_user: real_user.get_balance(),
  ).bind_optional(  # This won't be called if `real_user.get_balance()` is None
      lambda balance: balance.credit_amount(),
  ).bind_optional(  # And so on!
      lambda credit: choose_discount(credit) if credit > 0 else None,
  )
https://github.com/dry-python/returns#maybe-container

You can decide for yourself what is more readable: all these lambdas or the `None and f()` code.


The dry-python lambda soup is awful, I totally agree there. That's just there mostly for demonstration purposes though. Generally you'd actually use the flow construct (monads) to compose methods.

But `obj and obj.method()` really is not the same thing as `obj.map(method)`. "virtual Maybe container/box" is a nice idea, and does actually type-check with mypy (mostly), but you cannot actually compose it with other functions. The problem is, each time you do `obj and obj.method()`, you end up union-ing type(obj) and type(obj.method).

https://mypy-play.net/?gist=5b03d81a64453997984e448df9b889e7

    main.py:40: note: Revealed type is "Union[__main__.User, None]"
    main.py:41: note: Revealed type is "Union[__main__.User, None, builtins.float]"
    main.py:42: note: Revealed type is "Union[__main__.User, None, builtins.float]"
    main.py:43: note: Revealed type is "Union[__main__.User, None, builtins.float, builtins.str]"
True Maybe types are more precise. Maybe if the Mypy engine could be retooled to recognise the `obj and obj.method()` idiom as tantamount to `obj.map(method)`, this could be avoided.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: