Hacker News new | ask | show | jobs
by chrisseaton 2374 days ago
The idea of Maybe is that you usually don't check for None. The idea is that you use it sort of like a collection in most cases, allowing the None to propagate up as the result of collection operations on other Nones. The issue can be that you get a None at the end and it isn't clear where it came from originally, and how it reached you. Adding stack trace information to each intermediate None, when in debug mode, can help you trace what went wrong.
1 comments

>The idea is that you use it sort of like a collection in most cases

Sort of like a monad, even!

Honestly if you're running into problems like that though you should probably be using Either instead of Maybe like GP suggested. In my opinion, most of the benefit is still derived from strong static type checking, because otherwise you basically have to trust that callers respect your contract with these types. Perhaps Ruby 3.0 will make this feasible. I'm not sure of the details of the type system they intend to implement; whether it supports ADTs and such.

> Sort of like a monad, even!

Yes that's it - they're monads! Either is also a monad, and you can store error information in the other side if you want, but a good thing about Maybe is it could transparently store the error information, and produce it when debugging, rather than baking it into the normal runtime semantics.

> you basically have to trust that callers respect your contract with these types

This is table-stakes for a dynamic language like Ruby, though. Yes people can do anything, but usually they follow the rules they're given.

Yes I’m aware they’re monads, my primary languages are OCaml and Haskell. I don’t understand what you’re suggesting with Maybe, that sounds like maybe adding some layer of magic onto it?

> Yes people can do anything, but usually they follow the rules they're given.

Sure, but the primary advantage remains in not having to trust that, not having to write tests for it, and communicating the contract itself inside the code it restricts. I’m just honestly not sure what purpose they serve here, and why you’d bother to call them monads when what you really seem to want is the stored debugging information.

> I don’t understand what you’re suggesting with Maybe

I’m suggesting adding a trace of where a None value is created and propagated, for debugging purposes.

> the primary advantage remains in not having to trust that, not having to write tests for it

Is that the primary advantage? I’m not as sure as you seem to be.

And of course there’s one huge part of monads that you have to take on trust even in Haskell isn’t there? The monad laws! No type system is enforcing those. If you’re comfortable trusting someone else is following that rule why is trusting they follow another so alien?

But if you don’t like the idea don’t worry I’m not going to come round to your house and force you!

>Is that the primary advantage? I’m not as sure as you seem to be.

It's the combination of that and exhaustive pattern matching that I see as the reason to use strongly-typed functional languages.

>No type system is enforcing those.

This is quite different from not having static type checks at all though. At least with static typing I know that bind and fmap have the correct signature, which is certainly not a verification that they follow _all_ the rules they should (though I am a big fan of dependently typed languages too), yet it is still assurance that the function fulfills a basic premise.

>If you’re comfortable trusting someone else is following that rule why is trusting they follow another so alien?

Because I have seem them betray that trust, over and over again, intentionally and unintentionally, though never actively malicious. Type checking is work the compiler can do for me, so I see no reason to do it myself, where I am known to be rather clumsy and stupid and prone to writing bugs and being human.