Live data from Hacker News

Maybe Functions

blog.benwinding.com

11–20 of 103 posts

Re: Maybe Functions

#11
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 think that's true for checked exceptions; in Typescript, I'd rather see that a function may return a null, rather than get surprised by a possible exception that's not telegraphed.

Re: Maybe Functions

#12
You do have another solution that can lower the amount of conditions: Null Objects. These don’t fit every use cases, but they can allow you to express what’s missing, or not defined, or empty, and avoid nil pointers dereference or conditions to check the state.

As Sandy Metz is used to say « Nothing is Something »[0]

0: https://youtu.be/OMPfEXIlTVE?si=qmizH1OvqV7eLKNK

Re: Maybe Functions

#13
> Here’s a specific example, it’s a “maybe” function as it only returns the friends of a user, if the user is logged in. Basically it introduces a possible return null.

    function maybeGetUser(): User | null {
      if (!loggedIn) {
        return null;
      }
      return fetchUser();
    }

I believe this is an error. The code sample I took from the article is about getting a user, not the user's friends.

Since that function will return a list, an empty List might work.

Re: Maybe Functions

#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 ensure the user is logged in before calling getFriends otherwise you'll get some kind of error, which might give you more control, but now there's no guarantee in the type system that you've handled the case where the user isn't logged in.

Writing ifs everywhere to handle failure conditions might be a bit of a pain, but that's more of a failing of the language than the style.

Re: Maybe Functions

#15
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 am for exceptions but it should not be used for basic control flow. Many techs will treat all exceptions as errors.

Re: Maybe Functions

#16
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 think that's true for checked exceptions; in Typescript, I'd rather see that a function may return a null, rather than get surprised by a possible exception that's not telegraphed.

I think that's my biggest problem with exceptions. I have to rely on the doc comments to figure out whether a method can throw exceptions and which and when. And who knows if that covers all the possible exceptions from all the code that method relies on. It entirely sidesteps the type system and means I can't rely on the input/output types when using a method.

Re: Maybe Functions

#17
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 am for exceptions but it should not be used for basic control flow. Many techs will treat all exceptions as errors.

Interestingly, Python uses exceptions for basic control flow, like end of for-loop.

Re: Maybe Functions

#18
The proliferation of conditional "maybe" functions is a sign that your call graph is contrived and unnatural. You shouldn't be checking "userLoggedIn == true" in each and every accessor function. Ideally, such checks should bubble up towards the top of the call stack, and be performed once in an event loop iteration. The calling code should make sure that some basic prerequisites are met.

Re: Maybe Functions

#20

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

If you just have 1 step then there is no advantage.

If you have multiple steps then the advantage is that you never have to unpack "in the middle" and you don't have to care - and the compiler has your back.

Classical example: show the street number of the user or show if there is no street number. There can be multiple things missing on the way and multiple transformations might happen on the way. E.g. the user might not even have an adress saved alltogether.

In that case, you only have to "check whether those Maybes contain values or not" once at the very end.

Post reply on HN