5 ms·
I'm not sure why do a <- getData b <- getMoreData a c <- getMoreData b d <- getEvenMoreData a c print d is better than var a = getDat
by AndrewDucker 9y ago
I'm not sure why
do
a <- getData
b <- getMoreData a
c <- getMoreData b
d <- getEvenMoreData a c
print d
is better than
var a = getData();
var b = a?.getMoreData();
var c = b?.getMoreData();
var d = c?.getEvenMoreData(a);
print(d);
Other than the "var" at the start of each line they look like they take up about the same amount space, and the pattern is near-identical, so they're equally readable.
- gnud 9y agoIn the Haskell example, a/b/c/d can be lists of simple data structures. In your c# style example, getData/getMoreData must either be methods on the a/b/c/d objects, or extension methods on lists of simple data structures. Both are pretty bad in comparison, IMO.
- pmilot 9y agoOthers have brought up good points, but I'd also add that the ad-hoc solution only supports calling methods on possibly-null objects. If you want to pass a possibly-null object to a function that does not accept null values, only the monadic solution works. In fact, you can see this in the example. AFAIK, the ad-hoc example will end up printing a null value, while in the monadic example, print is never called at all.
- beojan 9y agoAnd the question mark. And see how for d, there's no symmetry between c and a. The do notation is definitely more readable.
- saurik 9y agoBecause it is a general solution that solves every problem listed on that page, and more, instead of only solving that one specific problem of null value checking.
- alipang 9y agoThe point is not that any one example is better than the other, rather it's that the same syntax can be used to uniformly solve multiple different problems (partiality, async, "non-determinism", and state-passing).
- xenomachina 9y agoOne thing this article doesn't really make clear is how someone reading the code can actually determine which of these things is being done. Code that looks the same but magically does something different doesn't seem like an improvement to anyone who wants to be able to maintain their code. I know enough Haskell to know that the "magic" comes from which instance of Monad is being used, but between the weirdness of overloaded values, the fact that the "do" syntax doesn't really make it obvious which value is the important one, and Haskell programmers' aversion to using parens, I still find this stuff impossibly hard to read. This is largely why I gave up on Haskell after trying to learn it for 3 years.
- thinkpad20 9y agoThere are two answers I can think of: 1. You know what the code is doing to the extent that you know how monads work. As in, you know that you’re going to do some monadic action that returns a, then another one that returns b, etc. The code as written is generic so it’s not specified what the actions are. 2. And this is the much more common case; the code in question is being used within a particular context (I.e. for a particular monad that the programmer is working with) and the context makes it obvious what is actually being done by the monadic actions. Here the genericness is not in writing a function that can be used in multiple places, but in having a portable concept of “a pipeline of actions that return things and could fail” which you can use wherever you need it.
- platz 9y agoWhat resources did you use
- xenomachina 9y agoWhat kind of resource do you mean? It's been a few years now. I know I read LYAH, and I think also one of the O'reilly books. I used GHC and vim+syntastic. I used Hoogle for looking stuff up. I asked lots of questions on Stack Overflow, Reddit, and one of the IRC channels. Even after 3 years, everything with Haskell felt like rolling a boulder up a hill. The only reason I'd persisted as long as I did was because the idea of a purely functional statically typed language really appeals to me. Despite those features being what I've wanted in a language for decades, too much about Haskell makes it unusable for me. I did learn some useful stuff in the process, but came away with the conclusion that virtually all of the good stuff in Haskell does not really need to be coupled to all of the terrible stuff in Haskell. I think for some people (I suspect a tiny minority) of the people who attempt to learn Haskell, they get past the terrible stuff and either stop seeing it, or become brainwashed into thinking it's unavoidable/necessary. Perhaps it only works for the 5% of people who's brain happens to be wired the right way, I don't know. Most people, though, give up. To make matters worse, if you are not one of those people for whom the weirdness of Haskell "clicks", and you mention that parts of it make no sense to you, you'll get very little help from the Haskell community. Most will tell you things like "I use Haskell every day, and this doesn't bother me". Great. That said, during the time I was trying to learn Haskell I did see some small improvements being made in the usability department. The biggest by far was that they finally turned off MR by default. Still, too little too late for me, so I ended up giving up on Haskell and moving on to other languages where I can actually understand my own code a day or two later. As an aside, MR was a great example what's wrong with Haskell: 99% of the time the language designers don't seem to care about usability at all, but the 1% of the time they actually try to do something to help usability, their attempts completely backfire. map vs fmap is another example of this, though not nearly as horrendous as MR.
- bunderbunder 9y agoIf you just focus on specific problems, yeah, I agree, it's hard to see a great advantage. The magic is that having something like do syntax allows you to take matters into your own hands. You can relatively easily create your own solutions for these kinds of problems, without having to wait around for possibly years (or possibly forever) before the language implementors get around to giving you your Elvis operator or iterator blocks or async/await syntax or whatever.