52 ms·
Three Months of Go, from a Haskeller’s perspective (2016)
- demarq 10y agoI hate to sound like the rust evangelist strike force... I really do. But your complaints are exactly what it would solve... Sigh I hate to say this I really do. But here goes... So have you checked out rust?
- dualogy 10y agoHow robust/mature is it as of yet? More importantly, how are compile speeds and how much of a priority are they to the compiler maintainers? I too find it quite promising in terms of "a language aiming for the benefits of Go with the expressiveness and added easier correctness of FP". But "promising" doesn't mean I'd replace the few use-cases where Go currently shines for me (wouldn't recommend it for any-and-all development at all, but there are select cases where I currently absolutely wouldn't use anything else) as these are those few programs where I really want to write (and later, read) exactly step-by-step "almost machine instructions" and where the only "expressiveness" needed is already fully afforded by Go and quite well at that. Dev-related mostly bulk-file-processing-based custom tooling (not bad to fire off sizable amounts of automatic background transformations from one weird format to another on file-system events etc.) .... filters through which to pipe vast/continuous data streams with just-some-processing over it .... providing out-of-process certain "low-level, must be lightning fast" tasks and logic with IPC for a higher-level codebase .... it's a great tool for such cases, especially given how simple the syntax is. Ie. the basics are grasped very easily very quickly and you don't have to recall "its pattern matching syntax and quirks, its generics syntax and quirks, its etc etc". =) I'm perplexed when teams choose to express their entire domain model or startup in Go, however.. fair game, maybe I'm missing something there
- demarq 10y agoMy comment is aimed at the OP who has it very clear in their mind what Go's shortcomings are. On the contrary, you haven't pointed out an objective issue that you have with Go. You offered some harsh remarks about the language but backed them up with praise. I'd say you love the language, but apologetically so. You shouldn't it's a great language. If ever you decide it's not for you then look at other alternatives, rust being one them.
- dualogy 10y ago> I'd say you love the language, but apologetically so. You shouldn't it's a great language. I just think for me it absolutely shines for certain use-cases and sucks for many others, where I simply won't use it. The question then becomes "why Rust over [Haskell&friends]", not "why Rust over Go" ;)
- merb 10y ago> How robust/mature is it as of yet? More importantly, how are compile speeds and how much of a priority are they to the compiler maintainers? I too find it quite promising in terms of "a language aiming for the benefits of Go with the expressiveness and added easier correctness of FP". I never get the compile time argument. Well I code a big Scala application and the most time it spents is integration testing. the 10 minute test suite would probably still run 9 minutes and 30 seconds on go. we heavily rely on the database and cover a lot of concurrency/parallelism things in our tests. some things which we would need to test in go, too. the compile time argument always looks good on first, but later on it's just a dumb way to prefer a language since it never matters. (Actually even the go maintainers didn't cared for a while about the compiler performance).
- cube2222 10y agoWell, the thing is, with compile times of 2 seconds I can run my unit tests as fast as possible. At the same time, I'd just use a mock database for most of the tests. It's great to be able to compile applications like kubernetes in 2 minutes.
- NateDad 10y agoDoes kubernetes take 2 minutes to build? That seems super long. I csn compile juju (1mil LOC) in like 15 seconds.
- AsyncAwait 10y ago
- steveklabnik 10y ago> robust/mature Needs more context. It's more mature for some things than others, like many young languages. > how are compile times Not Go, for sure, but not the worst either. > how much of a priority are they Getting them down is a high priority, but has taken some time to make a dent in. The last few releases have all posted speed ups, and "cargo check" in the last release helps. Incremental recompilation is coming, you can try its initial implementation on nightly today. There's a lot more to do, but users really want improvements, so it is and will continue to be actively worked on.
- dualogy 10y ago> Incremental recompilation is coming Good to hear, when that is in place compile times matter a whole lot less
- pja 10y agoOr Swift - Swift sneaks in sum and product types via a c-structy syntax. Once you see the type system underneath the syntax (which was devised not to scare the Objective-C horses IIRC) it’s quite pleasant.
- runeks 10y agoThis may be solved for Haskell as well in the near-ish future (I assume you're thinking of the GC issues) by the addition of linear types to GHC: https://news.ycombinator.com/item?id=13866787 https://news.ycombinator.com/item?id=13866787
- willsewell 10y agoWe're asked this question a lot (I work at Pusher). I wrote up some of my thoughts on this in reply to a comment on one of our previous blog posts: https://www.reddit.com/r/programming/comments/5fyhjb/golangs_realtime_gc_in_theory_and_practice_pusher/daowdag/ https://www.reddit.com/r/programming/comments/5fyhjb/golangs.... Right now I'm keen to get more personal experience with Rust, and hopefully in the wider team. I'm particularly interested in [Tokio](https://tokio.rs/ https://tokio.rs/), which should address some of our concerns about the existing concurrency support. Also, in same reddit comments there's a longer (quite argumentative) discussion on Rust concurrency that you might be interested in: https://www.reddit.com/r/programming/comments/5fyhjb/golangs_realtime_gc_in_theory_and_practice_pusher/daovtcc/ https://www.reddit.com/r/programming/comments/5fyhjb/golangs...
- steveklabnik 10y agoSmall update on that thread: Tokio has now had an initial release, with a lot of docs. Still much more to do, of course :)
- twic 10y ago> I hate to sound like the rust evangelist strike force... I really do. But your complaints are exactly what it would solve... Rust doesn't have lazy evaluation, or a particularly extensive standard library. I'm not aware that Rust has heap or thread profiling any better than Go's. For everything else, though, yes. I found Rust pretty easy to learn (coming from Java with a bit of Python background); i haven't mastered lifetimes or coherence, but i manage my day-to-day work without needing to. No GC means no GC pauses, and if there are big slow drop cascades, they are at least confined to one thread. Rustfmt seems to be mostly reasonable. Library versioning is done properly. The type system provides generics, sum types, and strong, if unconventional, control over side effects. Godoc uses source order and Markdown. Struct fields have to be initialized. Boilerplate is minimal; in particular, checking errors is one character, and sorting detects and uses an existing. ordering, or takes a single function to define one.
- deleted 10y ago[deleted]
- wyager 10y agoMost haskellers are fond of Rust. However, it is certainly not a Haskell replacement; it has substantially less expressive power. This is, arguably, necessary for its impressive memory model (no GC and memory safe allocation), but it does hurt programmer productivity in many cases. I always feel constrained when I use Rust, although I can't fault the language for being that way. Rust is well-designed, but even good designs come with caveats. I prefer Haskell's caveats for most common programming tasks. Personally, as a frequent Haskell user, I'm looking forward to replacing embedded C/C++ with Rust as soon as they get the AVR toolchain figured out and there's better support for common ARM uCs.
- Ar-Curunir 10y agoLuckily, LLVM 4.0 added support for AVR, and hopefully Rust can take advantage of this soon
- jonnybgood 10y ago> Go is just too different to how I think: when I approach a programming problem, I first think about the types and abstractions that will be useful; I think about statically enforcing behaviour I see statements like this a lot from Haskellers and I think its overstated. Anecdotally, after going from Python to spending 3-4 years in Haskell then going back to a dynamic language (Elixir) I've come to the conclusion that how you think when programming is very much a learned trait that works for that language. It's neither good or bad, but it's educational nonetheless. Haskell and other languages like it forces you to have a very unique mindset that can overpower previously learned languages not like it. And it's in no way permanent. After I stopped using Haskell I was like "ugh, I need types! wth!". I wanted to go back to Haskell only out of familiarity, but as I continued after a short while I wasn't even thinking like that anymore. The thought rarely occurred. I stopped thinking in Haskell and started thinking in Elixir.
- bad_user 10y agoI cannot speak for Elixir, but coming from the Erlang world, I'm sure it's a fine language that has sane defaults, much like Clojure. However I switched from Python to Scala and besides the performance issues and the poor handling of async I/O that I had with Python, by far the biggest problem with Python was all the insecurity while developing with it. It drove me insane, because we had a production system that always had problems due to how poorly Python's ecosystem treats errors. Just to give an example, at that time we were using BeautifulSoup to do HTML parsing, a library resembling JQuery, except that BeautifulSoup can return nulls all over the place and no matter how defensive I got in my coding, null pointer exceptions still happened. And what was the solution for async I/O in Python? Monkey patching the socket module by means of Gevent or Eventlet of course, which didn't work for native clients (e.g. MySQL's) and if this wasn't problematic enough, you had to guess what worked or not and when. The worst kind of magic possible. When I switched to Scala, all of these problems vanished. This isn't about having tests either, because tests only test for the behavior you can foresee, unless you do property-based testing with auto-generated random data and in this regard static languages like Scala and Haskell also rule due to the availability of QuickCheck / ScalaCheck. You see, my Python codebase got really bad because of fear of refactoring. Yes, even with plenty of tests and good code coverage. Because actually the tests themselves became a barrier for refactoring, because in a language like Python there is no such thing as information hiding and coupled with dynamic typing, it means that your tests end up tightly coupled with implementation details, will break on correct refactoring and will be hard to fix. Nowadays when I'm doing refactoring with Scala, most of the time it simply works as soon as the compiler is happy. Some people bitch and moan about that compiler being kind of slow and it is, but the things that it can prove about your code would require specialized and expensive tools for other languages and that wouldn't do such a good job. Going back to dynamic languages, there are also languages like Clojure, which get by with sane defaults. For example in practice Clojure doesn't do OOP-style dynamic dispatching most of the time and functions are usually multi-variadic and capable of handling nil values gracefully. This is not enforced by the language, being simply a hygienic rule accepted by the community. However, relying on such conventions requires (a) capable developers that (b) agree on what the best practices should be. And the issue that people miss when thinking of the merits of such languages is that smaller communities are always homogeneous. So when giving as example a language like Elixir, if it hasn't drove you insane yet, well, you have to take into account that Elixir might not be popular enough. So basically I prefer strong static typing because I'm not smart enough or wise enough to seek and follow best practices as often as I'd like and because I don't have much faith that other people in the community can do that either, especially after that community grows. The biggest irony imo is that Python is right now the anti-thesis of TOOWTDI.
- solidsnack9000 10y agoPulling no punches: Other than that, I will probably never choose to use Go for anything ever again, unless I’m being paid for it. Go is just too different to how I think: when I approach a programming problem, I first think about the types and abstractions that will be useful; I think about statically enforcing behaviour; and I don’t worry about the cost of intermediary data structures, because that price is almost never paid in full. Wow.
- solidsnack9000 10y agoThe cost profile for data structures is different in Go, though, since it tries to stack allocate very aggressively. GHC, like Java and many other classical GC'd languages, tends toward heap allocation.
- deleted 10y ago[deleted]
- bboreham 10y ago> There is no way to specify a version [of an imported package] You can do this in your version-control system (e.g. git), via a process called "vendoring". It's ugly but, using one of the popular tools, quite workable.
- dualogy 10y ago> It's ugly What do you find ugly about it?
- kuschku 10y agoYou don’t properly separate and deduplicate dependencies, you can end up with legal issues (if you ever decide to redistribute your source), etc. One of the few dependency systems I’ve seen that work well is Gradle with Maven dependencies, using Java 9’s versioned modules. Proper versioning, proper dependencies, etc.
- bboreham 10y agoThe idea of copying multiple other repos into mine. I have used git submodules to avoid copying, but if one library has its own vendor'd copies you can end up with two versions of the same dependency. Which is even more ugly.
- joaodlf 10y agoI feel like some of the criticism is unwarranted, specifically: > The tooling is bad I feel like the tooling is really impressive, considering the age of the language. Remember that Haskell is something like 25+ years old. Go has done quite a bit in short time - I can only hope it will get better too. > Zero values are almost never what you want I've always felt the defaults to be spot on. Anyway, it's my responsibility to initialise these values, even on struct fields. > A culture of “backwards compatibility at all costs” I agree the current (package management) landscape is dire, but this should change, hopefully this year, with godep. As it is now, I have found success using glide for dependency management, so that's what I would recommend for now. Apart from that, I can agree on a lot of things - I'm specifically annoyed by the whole generics thing, the way I interpret the people involved with the project is "it would be nice to have, but the implementation is awkward, so we won't admit to it being nice to have".
- AsyncAwait 10y ago> Remember that Haskell is something like 25+ years old. Yet, I'd argue that tooling is still one of the worst aspects of the language. The whole cabal/stack thing is a mess.
- pjmlp 10y agoYet, at least we can use proper versions instead of Git urls that are exposed in source code.
- dualogy 10y agoThese import paths aren't really URLs. They're local import paths, where Go's out-of-box tooling additionally allows for far simpler package install/update flows when one chooses to have these local paths replicate remote-repo URL paths. One doesn't have to, but it essentially turns "any CVS" into what would be Hackage/Stackage in the Haskell world. Sure, no curation, but `go get repo-url` has its charms too for quick iterations and experimentations. Vendoring is also entirely trivial (have a fork, update it from the original when it seems sensible to do so, undo when it turns out not to be). And guess what, with that you have "reproducable builds". I like the hackage/stackage model, too. As long as there is always some folks tending to those repos. But, the `go get` model is a fine workflow too.
- PaulRobinson 10y agoTL;DR: "Go isn't like Haskell, and that means it's not as good" I get that we all have favourite languages, but it is not amazingly helpful to try and compare them like this, for me. I'm sure if you're a Haskeller and you're eyeing up Go, being forewarned might be helpful, but here's another idea: Don't compare. Just use. Take it at face value. Figure out what becomes easy, what becomes hard. I came at Go from 10+ years of professional Ruby development, and it was a tough punch to the stomach at times. I still think in Ruby more often than I think in Go. But I know the two aren't really comparable for most things.
- icebraining 10y agoI don't understand. How can they not be comparable? They're the same type of tool, built with the same goal (writing any kind of software). In fact, Go itself was born because its creators felt the current languages weren't good at handling the current computing environment - comparisons with other languages are the at core of its existence. Finally, why even choose Go if it's not because it has some comparative advantage? Might as well stick with what we already know.
- cube2222 10y agoThey're not the same type of tool. Go is mainly aimed at distributed computing evironments and infrastructural tools. I really don't see a sensible Consul/Kubernetes/Docker alternative being written in Haskell.
- dalailambda 10y agoI don't see why not, Haskell has green threads, channels, and everything that Go has. The only argument I can see made is that the laziness and current GC implementation aren't suited, and even then, those problems can be solved with strictness pragmas, and a different GC respectively.
- runeks 10y ago> I really don't see a sensible Consul/Kubernetes/Docker alternative being written in Haskell. The only reason for this is the unpredictable latency issues caused by the current garbage collector in GHC. This should be avoidable once GHC has linear types[1] and someone rewrites its GC to take advantage of this. [1] https://news.ycombinator.com/item?id=13866787 https://news.ycombinator.com/item?id=13866787
- jwdunne 10y agoIt is, I think, going to be very difficult to enjoy writing code in a less powerful language when you are exposed to languages that hold awesome power. In fact, this has been the basis for much writing on Lisp too. Paul Graham has written entire essays along the same lines. If you work in a job that forces the use of a less powerful language than what you've been exposed to, you can, I think, go through a sort of depression. You simply long to use the tools that you know hold much more power yet must resign yourself to the tools you have. You can overcome the problem by being present in your work. The language might be ugly. It might be totally underpowered with limited means of abstraction and a type system that snmacks you and, sometimes, your client over the head. What you can do is, despite that, commit to writing great software with the tools you have. Commit to improving your work. Perhaps expand the ecosystem with tools borne of insights from your adventures with high-powered tools. You will have a much more enjoyable time in most languages this way. Perhaps except MUMPS but there might be hope.
- bobsam 10y agoTL;DR : get off your high horses and get to work
- jwdunne 10y agoOr perhaps "we are programmers - if you wish for X in a language, make it so". Maybe a bit too long? I certainly don't want to sound prickly :)
- agumonkey 10y agoI ended up calling this engineering. Language is just a mean to an end, and learning its limits, picking one that match the most the problem at hand. That said FP/Lisp are very hard to leave, I can understand that.
- iagooar 10y agoIsn't it possible to choose the best tool AND get to work? Isn't it our responsibility, as software engineers, to ensure that those who pay for our services get the best bang for their buck? That includes choosing a programming language that actually helps developing new features faster, while guaranteeing that the system is available, robust and maintenance costs are low. Choosing a language that makes these things difficult, is a poor choice. We should not accept subpar languages to be used just because.
- shadowmint 10y agoI don't think anything in the 'The Bad' is unfair, and they're certainly not written from a position of ignorance. Those are things that suck about go; it's not specifically that they suck about go when compared to haskell; they just generally suck (particularly the type system stuff). However, I don't think that the situation is so bad I would go as far as to say, "Other than that, I will probably never choose to use Go for anything ever again..." I maintain that while go might not give smart programmers the flexibility to express their FP dreams, it has a grungy practicality both for developing and maintaining code that is quite effective. Introducing go and building applications with it in a team is easy because its quick to pick up for the whole team, regardless of background, its simple to use and its (relatively) difficult to shoot yourself in the foot in terms of distributing binaries or developing applications that run at modest scale. When gogland (the IDE by jetbrains) comes out of EAP, it'll even have a modestly good professional IDE with integrated debugger (no atom, you don't count when your debugger never works on any platform). ...but hey, if you don't like it, don't use it. Haskell is pretty great too.
- pjmlp 10y agoThe thing with Go, is that it is disappointing what Google is capable of in terms of language design versus what Apple and Microsoft have done in this field. Sure there were languages with such type systems before, and we managed to deliver our work with them. However I don't want to work in 2017 as I used to work in the mid-90's, when templates were an experimental feature in C++, or the only MLs we knew were Caml Light, Miranda and SML. The world has moved on.
- dualogy 10y ago> is that it is disappointing what Google is capable of Man, how long will this meme survive? Go only initially originated with some Google developers, it's not in any way "Google's answer to Apple's and Microsoft's strategically-important and accordingly-subsidized-and-evangelized-and-invested-in languages". Just picture a handful of (previously "accomplished" in the field, as it turns out though) guys thinking "this company has a wide mess of Python etc scripts that should really be C programs, except for the problems this would pose"..
- luigi23 10y agoOfftop: what kind of static website generator did he use? Looks clean, looking for something similar for my usage.
- niel 10y agoThe author's site appears to be built using Hakyll https://jaspervdj.be/hakyll/ https://jaspervdj.be/hakyll/, which is a Haskell static site generator. You can find the source for this particular site on Github: https://github.com/barrucadu/barrucadu.co.uk https://github.com/barrucadu/barrucadu.co.uk The "clean look" you refer to is mostly thanks to custom CSS though - nothing specifically related to Hakyll. If you're thinking about building a similarly-styled blog or personal site, you could start by studying the styles this author used on their site: https://github.com/barrucadu/barrucadu.co.uk/tree/master/css https://github.com/barrucadu/barrucadu.co.uk/tree/master/css
- deleted 10y ago[deleted]
- krylon 10y agoI liked this conclusion: "Go is just too different to how I think" It is in a way a mirror image of my experience with Go: It is not so much that Go is a great language, it has its fair share of flaws, but it is quite compatible with the way I think.
- fpoling 10y agoThe author mentioned that code generation "introduces additional, non-standart syntax". One can say exactly the same about generics. Most useful typesystems with generics are Turing-complete. Essentially they introduce own language for types with often very weired rules and syntax that one has to master on top of the basic language. With code generation I can program my types using the same language I use for code with less things to learn.
- bad_user 10y ago> One can say exactly the same about generics No, it's the same language with a bigger vocabulary and grammar, on which everybody agrees. And generics can be quite sane, as exemplified by the languages in the ML family, which have been around for decades. Java also didn't have generics. They added them eventually, much later in version 5, but then due to backwards compatibility concerns they added them with invariance at the declaration site and complex wildcard rules at use site. So the irony of this situation is that Go will add generics, it's inevitable for a (quasi) static language once it grows in usage and ecosystem. But when they'll do add those generics, they'll be broken due to backwards compatibility concerns, becoming yet another counter example for generics, picked up by the next Go / Java that will reinvent the wheels again.
- fpoling 10y agoThe ugliness of Java generics comes from type erasing. It allowed to stay compatible with JVM. Go has no such restrictions and I do not see why a truly minimal generics in a style of Virgil cannot be added to Go at some point.
- bad_user 10y agoNo, type erasure is actually an (unplanned) feature, because it didn't cripple the runtime for other languages. On this one people miss the forest from the trees. dotNET type reification is about introducing runtime meta-data and checks, which you only need when your type system is not strong / expressive enough, which makes you want to do `isInstanceOf` checks. Well, guess what, needing to check that an instance is a List<int> is a failure of the language ;-) This issue is also mixed with specialization for primitives. But that's actually unrelated because you don't need reification to do specialization. And actually you don't need runtime support either, as specialization can be compile time. Also, in actual practice with Java, type reification is only a small usability issue. The real clusterfuck have been those wildcards for expressing use-site variance. > It allowed to stay compatible with JVM. Go has no such restrictions That's circular logic, given the JVM release cycle is tightly linked to Java the language and has had evolved in response to new features of Java. No, the actual reason was to preserve compatibility with older code that weren't using generics (e.g. List vs List<int>) without forking the standard library in pre- and post-generics functionality (like .NET has done). Go will have exactly the exact same problem.
- jrobn 10y agoI started out liking Go. It looked like a fairly pragmatic language. As I got deeper into my evaluation project (simple api stuff) it felt more and more like cutting wood with a dull saw. I started out liking Haskell too! But has I moved along with my small evaluation api project it felt more and more like I was trying to cut wood with gyroscopic laser saw. It worked but it was a lot of fan fair for sawing some wood. Picked up erlang/elixir. Looked pretty decent. Felt like cutting wood with a Japanese pull saw, so I had to use the vise clamps that came with it. It cut some fucking wood. ~ Ron Swanson out.
- pmarreck 10y agoi had to google "japanese pull saw" but as someone striking out into the elixir camp/world, this is also what I'm seeing
- Buttons840 10y agoMy impression of Elixir and Erlang are that they are the only dynamic languages I'm aware of that seem to have dynamic typing for solid technical reasons. Many languages are dynamic just for user experience reasons. But the way the BEAM VM handles hot code swapping, concurrency, and memory management, etc, required using a dynamic language. (As far as I'm aware?)
- jrobn 10y agoI think it's because of the built-in nature of message passing in the language. It's just easier to send around messages to processes. Hot code swapping would be possible with other JITed languages (BEAM isn't a JIT). Also since erlang has excellent pattern matching (even on binary data!) and a supervisor system (OTP) errors are easy to recover from. Erlang takes a very pragmatic approach of building tools that deal with errors by recovering from them instead of trying to exhaustively trying to prevent them.
- willsewell 10y agoI worked with Michael on the same project, after also working with Haskell previously. On the whole I agree with the pros/cons stated in the article. Having said that, my conclusion would be a bit different: I would err on the side of Go for the majority of commercial projects. The article mentions the impressive worst case pause times of Go's GC. Since then we have performed some additional benchmarking. The conclusion was: it is impressive, but there are still a couple of issues that break the sub 1ms claims. We blogged about this here: https://making.pusher.com/golangs-real-time-gc-in-theory-and-practice/ https://making.pusher.com/golangs-real-time-gc-in-theory-and.... It's hard to guarantee low latency in all cases... Michael also mentions that there is nothing like ThreadScope, or at least nothing that's easy to find. The latter is true. There is an impressive runtime system event visualiser which can be opened with `go tool trace` https://golang.org/cmd/trace/ https://golang.org/cmd/trace/. You can see a screenshot of this in the GC blog post I linked to above. Unfortunately the only documentation is this Google Doc: https://docs.google.com/document/d/1FP5apqzBgr7ahCCgFO-yoVhk4YZrNIDNf9RybngBc14/edit https://docs.google.com/document/d/1FP5apqzBgr7ahCCgFO-yoVhk... which is tricky to find, and could be more in-depth. I'm in the middle of writing a blog post on how to use this too. Watch out for it on our engineering blog in the next month or two. https://making.pusher.com/ https://making.pusher.com/
- gothrowaway 10y agoWhen I look at a programming language, I look at the community and how it gets stuff done and projects that are noteworthy. Something about Haskell strikes me as different. Despite the buzz about it, I don't see many projects for it other than shellcheck, pandoc and xmonad, and for two of those, there's better solutions around (sphinx, awesome/i3). The other thing is the general flow I've see with Haskell programmers, many really tie down their identity do it. They see programming as a crossword puzzle for them to solve in short term, not as something other programmers have to read later on. They're not very empathetic to the idea the runways dwindling and you have to ship sooner rather than later. In addition, I found that the Scala / Haskell developers I knew took golang to be quite the nuisance. They find gophers pesky. I think the reason why is years of Haskell teaches them to overengineer and complicate things needlessly. It's frustrating because they're not aware of it themselves and take offense, even blame you when you point it out to them. Maybe I've just been unlucky. In 10 years, I've never had people who consistently failed to ship, been mean and arrogant as scala / haskell programmers. They take the slight criticism as an assault on their identity.
- 59nadir 10y ago> Despite the buzz about it, I don't see many projects for it other than shellcheck, pandoc and xmonad, and for two of those, there's better solutions around (sphinx, awesome/i3) I tried awesome for two weeks and had one crash. I've run XMonad for 5+ years and had no crashes. Just because they are supposed to accomplish the same things does not mean that they're equal. One is better and it's because of the choice of language. It's very hard to take your post seriously when you include something like this in it and you don't bother to qualify it even in the slightest.
- gothrowaway 10y ago> One is better and it's because of the choice of language. > It's very hard to take your post seriously when you include something like this in it and you don't bother to qualify it even in the slightest. I looked in your history and yup, you are partial to Haskell. Why do you feel a need to immediately judge. Why did you say "hard to take seriously". Why didn't you just ask politely for more details? In my opinion, you already had your mind made up. Just like the blog poster did. > I tried awesome for two weeks and had one crash. I've run XMonad for 5+ years and had no crashes. That's your personal anecdote. There's no evidence that the language could have prevented the crash. And that doesn't make the window manager "better", which is subjective. What are more people using? Awesome and i3. Primarily because they don't want to deal with Haskell when they could be doing lua or a simple config.
- amelius 10y ago> GHC’s garbage collector is designed for throughput, not latency. It is a generational copying collector, which means that pause times are proportional to the amount of live data in the heap. To make matters worse, it’s also stop-the-world. This is pretty much unacceptable in today's world of low-latency (web) apps. How active is GHC's development? Would it be possible to efficiently run Haskell using Go's runtime environment, i.e. by changing the compiler backend?
- thesz 10y agoIf you have not too much data in the heap, you are safe. Even if you have a lot of data there, you most probably fine too. As an example, see here: https://bazqux.com/ https://bazqux.com/ and the discussion is here: https://news.ycombinator.com/item?id=5961570 https://news.ycombinator.com/item?id=5961570 He was able to survive unexpected slashdot effect from being on the front page of Hacker news without even noticing it. He told me he went up one evening and found that there were tens of thousands of new users actively trying his site. So he added a couple of servers and went to sleep. GHC development is very active. And the answer to your last question is No.
- ruslan_talpa 10y agoI think you are under the wrong impression about the performance/speed of the Haskell with it's GC when used in the web context. http://www.aosabook.org/en/posa/warp.html http://www.aosabook.org/en/posa/warp.html
- 10y ago
- dorfsmay 10y agoI'll argue that Python PEP 8 was probably the precursor to gofmt.
- bogomipz 10y agoThe author states: >"Strict evaluation is typically better for performance than lazy evaluation (thunks cause allocation, so you’re gambling that the computation saved offsets the memory cost), but it does make things less composable. " Can anyone tell me what a "thunk" is in this context and also why it causes performance problems? The article linked to in the sentence results in a 404.
- staticassertion 10y agoThunks are values that have yet to be evaluated. For example '3 + 3' could be represented as a thunk, and there's no cost other than memory because you have not computed '6'. So you're skipping the cost of computation for a value you may never use, but you still have to represent the expression in memory somewhere. This can lead to large thunks building up, eating up memory.
- paulddraper 10y agoA thunk is saved state whose evaluation has been postponed. a = 1 + 2 if (condition) { print(a) } In a lazy system, if `condition` is not true, then `a` is never evaluated. This contrived example would be a poor place to have lazy evaluation though, as the overhead of deferring would exceed the cost of computing 1 + 2 up-front.
- mrkgnao 10y agoA thunk is an unevaluated value. Better, it's an unevaluated piece of code that returns a value when it's required. For instance, you can write x = [1..] which gives you a list of all the positive integers. Because of laziness (which thunking enables), this line runs just fine. The compiler allocates a thunk for x, saying "okay, I know what x is now". But x is never fully evaluated (because we don't really have enough memory!): it's only evaluated as far as needed. Indeed, typing head x -- this is 1 makes the interpreter print the first element of the list. The rest is still in a thunk. In memory, we have something like [1,<unevaluated thunk>] Now you can try doing head (tail x) -- this is 2 which evaluates the list only as far as the second element. Right now, in memory, the list looks something like [1,2,<unevaluated thunk>] You can do similar things with basically any other datatype, enabling cool stuff like [1]. However, having to evaluate (or "force") thunks repeatedly in tight loops can obviously degrade performance: printing a Haskell list like [1..10] requires you to evaluate the first element, print it, then force the next thunk to print the 2, and so on. Comparing this to the equivalent in basically any other (strict) language, we see that a lot of indirection is removed, because the endless wrapping/unwrapping is replaced with a simple linked list of 10 elements. (I'm sure GHC is smart enough to optimize the thunking away in this toy case sufficiently.) One might also say that a thunk is a "promise" (I'm not familiar with the JS concept of the same name, which I think is related to async things instead) to give you a certain value by calculating it only when you need it (if you do at all: a thunk stays unevaluated when you're done running the program, it's GC'd away). [1]: http://jelv.is/blog/Lazy-Dynamic-Programming/ http://jelv.is/blog/Lazy-Dynamic-Programming/
- blacksoil 10y agoI think comparing Go and Haskell are like comparing two incomparable different species -- a fish vs. a cat. Why? Because Haskell is an interpreted language while Go is a compiled one. Interpreted language doesn't care much about performance as it isn't designed for that purpose, while in the other hand, compiled language does. As a result, interpreted language tends to be more 'elegant' and has lots of convenient features at the cost of performance. A concrete example is when you talk about preventing unacceptable data type in Haskell. They could make it so in Go, but the performance cost would be undesirable. IIRC, I read that they designed Go to be practical instead of 'elegant', the reason is so that people can learn it easily, making it a good alternative for other compiled languages like C++ whose learning curve is hugeeee and ugly!
- theseoafs 10y agoHaskell is a compiled language.
- the_why_of_y 10y agoThere is no such thing as a "compiled language" or an "interpreted language", as this is a property of language implementations: interpreters (GHCi, Hugs) and compilers (GHC, JHC).
- mrkgnao 10y agoGlasgow Haskell Compiler
- nv-vn 10y agoHaskell is compiled, and most of the safety features (i.e. everything in the type system) is checked statically at compile-time. Preventing unacceptable data types happens during compilation. The same could be done in Go with no performance cost.
- pmarreck 10y agoTL;DR: > I will probably never choose to use Go for anything ever again
- j2kun 10y ago> But Go does have generics, for the built-in types. Arrays, channels, maps, and slices all have generic type parameters. Doesn't this mean you could implement a generic tree type if you fix the underlying data structure to be an array/map? (Not a go programmer yet, but honestly curious)
- NegativeLatency 10y agoDefining the accessor methods would be the pain point there. The caller has to cast the returned object back to the correct type.
- edmccard 10y ago>Doesn't this mean you could implement a generic tree type if you fix the underlying data structure to be an array/map? Nope. There are only a few functions that accept type parameters, and they must be called with concrete types, and they only work with certain aggregate types. For example, "make" can only be used to create slices, maps or channels, so you could create a slice of 10 bytes with "make([]bytes, 10)" but you cannot write "make(T)" or even "make([]T, 10)" where T is a type variable, and you also can't do "make(Tree)" where Tree is, e.g, some struct type.
- woah 10y agoI think it's better to not even think of them as "generic functions". Think of them as language keywords which happen to have the syntax of functions.
- Thaxll 10y agoWell the fact that pretty much no one uses Haskell anywhere should give you some hints about the language iteself.
- daxfohl 10y agoHaskell always makes me sad. In real-world apps you always need hacks. I do anyway. In an imperative language I can be proud when my code only has a couple hacks in it. With Haskell I just end up feeling nasty about my code if there's even one hack there, and it makes me like coding less. (For toy apps with no deadline Haskell is great; the above regards Haskell-at-work, as a freelancer).
- quchen 10y agoFor me it’s quite the opposite: Haskell allows me to have local hacky sections that I can then hide in a module that exposes a safe API. Since refactoring is fairly easy with compiler assistance, I don’t even have to break up my 100-line-long work-in-progress algorithm with temporary names until it works – and once I have a working solution, converting it to something readable is mostly manually extracting definitions and giving them useful names.
- daxfohl 10y agoThat's nice. I haven't used it enough in a hacky way to come up with a list of good hacking patterns. Like I said, I always feel dirty, like I may as well be writing C, and then go do something else. Someone needs to write a book "REAL Real-World Haskell", with effective patterns for that kind of thing.
- twblalock 10y agoThis article's comments on code generation and generics are a good exposition of what I don't like about Go: it seems internally inconsistent, as though there is one set of features for the Go development team, and a lesser set for everyone else. The nice thing about Haskell and the Lisps is that they are consistently the same thing all the way down through every layer of abstraction, even at the bottom. There is no point where you reach the "magic" or "forbidden" layer where the paradigm changes and it turns into a different language. The problem with Go is that the code we programmers get to write feels like a DSL on top of the "real" Go, which uses constructs and "magic" we aren't allowed to take advantage of.
- SkyMarshal 10y agoGood writeup, but not an unexpected conclusion. I'd be very interested to see a similar writeup by a Haskeller on Rust, since the two are closer in some aspects (static enforcement of behavior, strong typing, well designed concurrency), but different in other key ones (strict vs lazy, GC vs manual, etc).