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

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.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: