TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Why Maybe Is Better Than Null

164 点作者 eventualEntropy大约 12 年前

24 条评论

egonschiele大约 12 年前
Aha, how timely! I just wrote this post on functors and applicatives that uses Maybe as an example: <a href="http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html" rel="nofollow">http://adit.io/posts/2013-04-17-functors,_applicatives,_and_...</a>
评论 #5578121 未加载
评论 #5578466 未加载
评论 #5581092 未加载
nilkn大约 12 年前
In comparison to Haskell, null in Java is similar to adding an implicit Maybe a instance for <i>every</i> type a.<p>In doing so, Java makes it just that much easier to create bottom values when they are not desired (e.g., dereferencing a null pointer).
评论 #5578559 未加载
tikhonj大约 12 年前
This article makes it seem like you'd have to explicitly check whether a Maybe value is Nothing when you use it. This is certainly <i>safe</i>, but it's also very awkward; as a contrived example, adding two numbers would look like this:<p><pre><code> case a of Nothing -&#62; Nothing Just a -&#62; case b of Nothing -&#62; Nothing Just b -&#62; a + b </code></pre> This is quite a bit of boilerplate hiding the expression that actually matters--a + b! Moreover, whenever you have code that creeps steadily to the right, it means you either messed up or missed an abstraction.<p>It turns out that this pattern--do a computation if all the values are present, but return Nothing if <i>any</i> of them are Nothing--happens very often. Happily, we can get some nice syntax for Maybe computations like this using do-notation in Haskell or for-comprehensions in Scala:<p><pre><code> do a &#60;- a b &#60;- b return (a + b) </code></pre> This is much better! It makes even more sense for more complicated expressions, especially when later results depend on values of earlier ones. However, for a simple example like a + b, it's still quite a bit of boiler plate; we can certainly do better! Here are two alternatives using functions from the Control.Applicative module:<p><pre><code> (+) &#60;$&#62; a &#60;*&#62; b liftA2 (+) a b </code></pre> The important idea here is that both versions somehow "lift" the (+) function to work over Maybe values. This just means they create a new function with checks for Maybe built in. This is great because it saves all the boilerplate above and nicely abstracts away most of the null checks while preserving safety. But the syntax is still a bit awkward. Happily, if you don't mind using a preprocessor[1], you can get some very nice syntax called "idiom brackets":<p><pre><code> (| a + b |) </code></pre> [1]: <a href="https://personal.cis.strath.ac.uk/conor.mcbride/pub/she/" rel="nofollow">https://personal.cis.strath.ac.uk/conor.mcbride/pub/she/</a><p>The computation inside the (| and |) is lifted over Maybe, just like the two previous examples. I think this is the clearest option here: it has the least syntactic overhead, and the base expression--a + b--is very easy to read. They also have the advantage of nesting, so you can express a + b + c, where you want a null check for all three variables, as:<p><pre><code> (|(|a + b|) + c|) </code></pre> This isn't <i>perfect</i>, but I think it's still very easy to follow. It might be better if the (| and |) were a single character, something like this:<p><pre><code> ⦇⦇a + b⦈ + c⦈ </code></pre> However, some people really don't like Unicode symbols in their code :(. Happily, you can have the source look like (|foo|) and have Emacs replace it with ⦇foo⦈ without actually changing the code. It's basically Unicode syntax highlighting. I think this leads to the most readable code so far.<p>So my main point is that you can abstract out the common case where you check for Nothing and make the whole expression Nothing if any sub-expression is. This saves quite a bit of typing and <i>much</i> more importantly makes the resulting code far easier to read.<p>Another really cool part is that all these syntax forms and functions are <i>not</i> specific to Maybe--they actually work for a whole bunch of different types. So you would not be bloating your language by including special features just for safely checking nulls; these features are much more general.
评论 #5577838 未加载
评论 #5577899 未加载
评论 #5577801 未加载
kelnos大约 12 年前
So maybe this is just a terminology thing, but, isn't Maybe the same thing as:<p>1. By default all types are non-nullable. 2. You explicitly mark if you expect that a value could be null. 3. The compiler helps you by either making sure you check for null on those values you mark, or by doing some magic (like Scala does) that will always return null for expressions where one of the values is actually null.<p>Is the reason we call it Maybe/Option/whatever just to disambiguate with the traditional use and lack of safety in what pretty much all languages use "null" for? Or is there a distinction I'm missing?
评论 #5578702 未加载
评论 #5578694 未加载
implicit大约 12 年前
I've been working with engineers writing production Haskell for the first time; its lack of a "null" concept is proving to be absolutely incredible. In a high-uptime production environment, it's at least as valuable as Haskell's enshrinement of purity.<p>We have a convention that all recoverable errors be captured in Either or Maybe. This policy is paying off in a huge way because the type system forces us to think about what error cases mean. This is driving us to write substantially higher-quality code than I've written with other tools.
评论 #5580703 未加载
qb45大约 12 年前
Another story is that you may end up with something like:<p><pre><code> Just x -&#62; something x Nothing -&#62; halt_and_catch_fire # impossible </code></pre> In Haskell there is even a standard library function <i>fromJust</i> which does exactly that.<p>One introduces this hack knowing that this particular variable will always be <i>Just</i> and having absolutely no way to deal with <i>Nothing</i> and later somebody else sees the type <i>Maybe Foo</i> and figures that it must be OK to put a Nothing in there.
评论 #5580617 未加载
ExpiredLink大约 12 年前
&#62; 1. The elimination of null. This means that all types (even reference types!) become non-nullable.<p>Yep, problem solved, 'billion-dollar mistake' corrected (at least for future times).
stickfigure大约 12 年前
I can't believe there is no mention of Ceylon here. Ceylon has an elegant approach to this using union types.<p><pre><code> Typesafe null and flow-dependent typing There's no NullPointerException in Ceylon, nor anything similar. Ceylon requires us to be explicit when we declare a value that might be null, or a function that might return null. For example, if name might be null, we must declare it like this: String? name = ... Which is actually just an abbreviation for: String|Null name = ... An attribute of type String? might refer to an actual instance of String, or it might refer to the value null (the only instance of the class Null). So Ceylon won't let us do anything useful with a value of type String? without first checking that it isn't null using the special if (exists ...) construct. void hello(String? name) { if (exists name) { print("Hello, ``name``!"); } else { print("Hello, world!"); } } </code></pre> From <a href="http://ceylon-lang.org/documentation/1.0/introduction/" rel="nofollow">http://ceylon-lang.org/documentation/1.0/introduction/</a>
评论 #5584213 未加载
评论 #5581718 未加载
taeric大约 12 年前
I think the largest hurdle I have getting running with maybe, is that it just isn't in my fingers yet. As such, it can really slow you down if you were trying to build a bare bones prototype without layering. Which, given the popularity of dynamic languages, I would think is fairly common.<p>That is, if you are going to use Maybe, you either want to do so from the beginning, or you want a good layer of abstraction between where the value is optional and where it is not. Moving something from guaranteed to optional is a bit more combersome with Maybe.<p>Also, I have gotten really used to "truthy" values.
vorg大约 12 年前
&#62; Grōōvy isn’t really about statically enforcing things<p>They added a statically-compiled mode to Grōōvy last year. Most users like Grails don't use it yet, but it's there to try out and you can report any problems to the Grōōvy issue tracker.
jayferd大约 12 年前
_why, Maybe is better than NULL. You can program without fighting NULL.
CJefferson大约 12 年前
How many problems are actually caused by null (in particular, how many billions of dollars?)<p>While pointers which point into the wrong place for various reasons (off end of array, previously freed memory) cause horrible issues to this day, I can't personally remember ever having a serious issue with a null pointer (they tend to crash quickly and loudly, because in all modern OSes dereferencing NULL segfaults)
评论 #5577742 未加载
评论 #5577741 未加载
评论 #5577776 未加载
评论 #5577737 未加载
评论 #5578267 未加载
评论 #5577846 未加载
wellpast大约 12 年前
@Nullable plus static code analysis gives me quite a bit of static-time feel goodness in Java without any need for Optional/Maybe.
rtfeldman大约 12 年前
Great article! I'm especially glad to see "what have we gained?" in the FAQ, as it is probably the most frequently asked question I've heard.<p>OP - I noticed you were thorough enough to mention both Fantom and Kotlin in one section, so for the preceding section you might want to note that CoffeeScript also has a safe-invoke operator like Groovy's.
评论 #5580713 未加载
radicalbyte大约 12 年前
In object-oriented modelling you often see the Null Object pattern being used to the same effect.<p><a href="http://en.wikipedia.org/wiki/Null_Object_pattern" rel="nofollow">http://en.wikipedia.org/wiki/Null_Object_pattern</a><p>It needs static analysis tools such as Code Contracts (C#) or SpringContracts (Java) to make it really robust.
评论 #5578465 未加载
jfb大约 12 年前
Relatedly, I've always been fond of Objective-C's nil, for languages without strong static typesystems.
pubby大约 12 年前
Does that article title pass a type checker? How can you compare a type (Maybe) with a value (Null)?<p>Is this instead arguing Maybe vs pointers? No, that can't be right; pointers are just type-safe as Maybe, albeit less general.<p>I guess it's a dynamic vs static typing argument in disguise?
评论 #5578080 未加载
评论 #5578795 未加载
anuraj大约 12 年前
making null fuzzy may save your program from a crash, but it also makes execution unpredictable. I would prefer a crash - which would lead to better localization and bug fixing - than indeterminate behaviour which is hard to debug and maintain.
CountHackulus大约 12 年前
Maybe IS Null, they're just two different implementations of monads.
评论 #5580499 未加载
Bjoern大约 12 年前
Does anyone have a nice implementation of the Maybe Monad for C++ ?
评论 #5579171 未加载
hmottestad大约 12 年前
Null != None<p>Null means unknown.<p>Take a look at the difference between open and closed world systems.
评论 #5580528 未加载
weakwire大约 12 年前
scala did it
Evbn大约 12 年前
Guava for Java has Optional. Very nice, except for Java's horrid syntax for generics.
评论 #5577581 未加载
dscrd大约 12 年前
If you work on types that might be null, you're bloody careful or you're in the wrong profession. We're not calling incompetent programmers a gazillion dollar mistake, even though they probably have caused as much.
评论 #5578711 未加载
评论 #5580540 未加载
评论 #5578635 未加载