Live data from Hacker News

Maybe Functions

blog.benwinding.com

41–50 of 103 posts

Re: Maybe Functions

#41

What's the advantage of the Monad approach? Doesn't the render function still have to check whether those Maybes contain values or not?

I dont think there is any advantage when the language lacks syntax level support for Monads. E.g. in Haskell (which does) it would look roughly like: getUser :: Maybe User getUser = ... getFriends :: Maybe [User] getFriends = do user renderBestFriends besties Nothing -> renderNoFriends The Maybe monad itself contains the equivalent of runSafely from the article, and the syntax propagates the failure case transparentl…

It saves you from having to write the null check code for other cases.

Re: Maybe Functions

#42
post #8

Agreed with this essay, and I think it rhymes with two others that I've found pretty influential over the past five years: 1. Parse, don't validate ( https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... ) 2. Pipeline-oriented programming ( https://fsharpforfunandprofit.com/pipeline/ ) In my experience, the "best" code (defining "best" as some abstract melange of "easy to reason about", "easy to modify", "e…

Parse, don't validate is fantastic. I read it a few years ago and I still think about it quite often.

Re: Maybe Functions

#43

And what if `fetchUser` hits an error? At the very least pop your de-maybeifier after the async call. Or use something language standardised (like a promise in JS where you can just throw). I'm all for a perfy shortcut / early return but this maybe just seems like an abstraction on a non-issue.

... And TBH the bigger smell is eminating from the explicit `null` returns. Next essay please.

Re: Maybe Functions

#44
post #35
post #14

Program logic fundamentally has to contend with different conditions. Sometimes the user will be logged in and have friends, sometimes they won't. The "maybe" style has the inconsistency embedded in the type system; it's impossible to have an invocation to getFriends and then not handle the resulting possibility of not being logged in. Shifting it up to the caller just means that you're going to have to remember to e…

I agree with this. I prefer explicit optional/null return types, otherwise the possibility of an error still exists but is now hidden to the caller. Langs with syntax for concise optional chaining and such fix this problem imo

Note that Typescript - the language of the examples - does have proper null through it's type system. A function that returns `T | null` will require callers check for null before using T.

Re: Maybe Functions

#45
post #37

I would argue that the vast majority of functions in real world software are maybe functions in that they can fail. You need to be able to deal with failure. Not only can the user not be logged in, there can be a network issue, etc that makes even downstream functions fail. Also, you have to deal with developer mistakes and what happens when they call incorrectly. This can be something as simple as getting the first…

> Also, you have to deal with developer mistakes and what happens when they call incorrectly. There is only one safe(ish) way to deal with programmer errors: crash. Hopefully loudly and early enough so it gets discovered in testing.

Why wait until then? The loudest and earliest crash you can get is a failure to compile with a rich type system (obviously, when possible).

Re: Maybe Functions

#46
post #26

I think the post is related tothe "Null vs Maybe" problem. See https://web.archive.org/web/20230329075114/https://www.nickk... already discussed here https://news.ycombinator.com/item?id=5577364

Except it isn’t. Returning ‘User | null’ in typescript is the same type-wise as returning Maybe

Re: Maybe Functions

#47
post #8

Agreed with this essay, and I think it rhymes with two others that I've found pretty influential over the past five years: 1. Parse, don't validate ( https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... ) 2. Pipeline-oriented programming ( https://fsharpforfunandprofit.com/pipeline/ ) In my experience, the "best" code (defining "best" as some abstract melange of "easy to reason about", "easy to modify", "e…

IIRC Rich Hickey says something similar to the "pipeline-oriented programming" piece in his talk about systems: https://www.youtube.com/watch?v=ROor6_NGIWU&pp=ygUccmljaCBoa...

Re: Maybe Functions

#48
post #6

Another option is Exceptions. The function either does what it's supposed to, or freaks out. You can remove the null checks and the software will raise a null pointer exception. In the first example, could raise a NotLoggedInException. It's still a maybe function, but you have a mechanism for expressing the why-notness of the function run, as opposed to returning a generic null. As an aside, I prefer the "Unless" mod…

I like the philosophy that “exceptions are for exceptional circumstances.” Not being logged in is not exceptional.

for a function called "getUser" it is.

Re: Maybe Functions

#49
What seems that the fundamental problem is that the functions depend on global state that is not explicitly passed in (is the user logged in?). Maybe an explicit session parameter could work better here. You only have a session when the user is logged in, so you can't even pass anything to the functions otherwise. It can of course be passed further recursively.

Re: Maybe Functions

#50
post #25

Earlier quoted context omitted.

I am for exceptions but it should not be used for basic control flow. Many techs will treat all exceptions as errors.

In this case, it's not being used for basic control flow. It's a prerequisite of the function that the user is logged in - and you violated that so it's an error. Returning null masks the reason why that happened. As others already said: you shouldn't even be able to call this function when your pre-requisites for calling it are violated, ideally. You can achieve that by putting this function inside some sort of obje…

So what I meant is that you see the exact same maybe pattern in many projects but instead of returning null there is a guard that throws an exception. I agree with the solution.
Post reply on HN