17 ms·
Rust as a gateway drug to Haskell
- slaymaker1907 9y agoSomething that I found about going from Haskell to Rust was that Rust provides many powerful abstractions without compromising on performance. It was very frustrating to try reasoning about performance in Haskell due to its laziness. Every language has quirks about how to write performant code, but Haskell is notorious in my mind for being quite easy to write obscenely slow code in.
- aaron-lebo 9y agoThis is what's really nice about Nim. It writes like Python, but is fast like Rust. Ran across Option in it the other day, though it's not used heavily. I really wish there was something like Haskell but with a runtime like Nim or Go. Perhaps that is OCaml?
- captainmuon 9y agoExactly. For me, Haskell was a gateway to Nim. I wanted something that feels familiar, but with a strong type system and native speed. I wish I could invest some time in working with Nim. It doesn't get as much attention as it deserves in my opinion, and it would really benefit from growing the community a bit.
- nicoburns 9y agoHave you looked at Swift? It's pretty similar to Rust, but eschews all the lifetime stuff in favour of a runtime that does reference counting.
- pjmlp 9y agoActually Swift 4.0 just got some memory ownership support, with more to come later.
- kibwen 9y agoLink? Last I checked all of Swift's ownership ideas were just in-progress proposals, with implementation to be left to far-future releases.
- pjmlp 9y agoWatch the video about the talk, what is new in Swift 4.0 at WWDC 2017. Basically 4.0 will introduce the notion of exclusive access, with more affine type ideas to follow up on 4.x. EDIT: This feature is described by SE-0176. https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md https://github.com/apple/swift-evolution/blob/master/proposa...
- beefsack 9y agoSwift is useful if you're an Apple developer only targeting Apple users, seems like a bit of a niche.
- AlexeyBrin 9y agoSwift works reasonably well on Linux. You can even run Swift on Windows 10 through Windows Subsystem for Linux.
- beefsack 9y agoI tried under Arch a few months ago and found swathes of the standard library didn't appear to work, is this something which has been fixed?
- AlexeyBrin 9y agoAFAIK only the core language is fully ported, for the libraries ... it is a work in progress.
- jandrese 9y agoIn other words it is useless currently.
- AlexeyBrin 9y agoTell that to IBM that uses Swift in production. See IBM's Kitura open source server framework if you are interested.
- jandrese 9y agoThey use a language without a standard library in production?
- 9y ago
- delhanty 9y ago>Every language has quirks about how to write performant code, but Haskell is notorious in my mind for being quite easy to write obscenely slow code in. +1 One approach that occurred to me was to use Haskell and Hackage for prototyping a design and then a Rust implementation for production. It also reminds me of this from several years ago: GHC honcho Simon-Peyton Jones saying the next Haskell will be strict, but still pure with effects only via monads. [1], [2]. Following on and presumably related to that PureScript is strict. [3] [1] https://news.ycombinator.com/item?id=1924094 https://news.ycombinator.com/item?id=1924094 [2] http://www.cs.nott.ac.uk/%7Egmh/appsem-slides/peytonjones.ppt http://www.cs.nott.ac.uk/%7Egmh/appsem-slides/peytonjones.pp... (PowerPoint) Slide 40 [3] https://github.com/purescript/purescript/wiki/Differences-from-Haskell https://github.com/purescript/purescript/wiki/Differences-fr...
- mrkgnao 9y agoI'm under the impression that SPJ made that comment thinking of adoption (for a future "regrettably popular" Haskell), since the difficulty of reasoning about laziness does put people off. I might be wrong though: maybe he was arguing that laziness doesn't warrant the user and compiler-author cost it brings. I don't remember where I picked this up from. Idris is strict too, but optional laziness is built into the compiler with the use of a special-cased Lazy wrapper of the form data Lazy a = Delay a This is kind of the opposite of strictness annotations (bang-patterns) from Haskell, except one doesn't need to pattern-match on Delay or use it to wrap arguments to functions expecting Lazy values. The Idris compiler can do something like "laziness analysis" (admittedly trivial in comparison to GHC's strictness analyser) to introduce and eliminate Delay constructors automatically. The laziness information is carried around in the types: force : Lazy a -> a force a = a https://github.com/idris-lang/Idris-dev/wiki/Unofficial-FAQ#can-i-have-lazy-evaluation-if-i-want-it https://github.com/idris-lang/Idris-dev/wiki/Unofficial-FAQ#... (purescript-lazy is also a thing, but I think it's not as seamless because of the "no compiler magic" position.) In any case, what about -XStrict? I've never used it (or -XStrictData either), but isn't it a solution to the laziness problem, albeit a nuke-ish one at that? And while we're thinking ahead, let's talk about the project to get linear types (something similar to Rust lifetimes, but weaker) into GHC :) https://ghc.haskell.org/trac/ghc/wiki/LinearTypes https://ghc.haskell.org/trac/ghc/wiki/LinearTypes
- oconnore 9y agoComparing it against Rust doesn't really seem fair. If I wasn't using Haskell, I'd be writing Erlang, and last I checked GHC is much faster than Erlang/OTP. Certainly faster than CPython, Ruby, and most Node.js. Trying to compete with Rust or C++ performance in Haskell is certainly frustrating to reason about :)
- pletnes 9y agoWhile "GHC is faster than CPython" is a fairly accurate generalization, I still think python performance is easier to reason about. Haskell can give you fast code, but sometimes it will be super slow for no obvious reason.
- motet_a 9y agoMoreover, CPython is a interpreter without JIT while GHC compiles to machine code. This is totally different. IMHO, it is much more correct to compare a JIT-enabled interpreter to GHC.
- chongli 9y agosuper slow for no obvious reason Obviousness is hard to pin down. What may be completely obscure to a Haskell beginner is obvious to a veteran. Is it really fair to count people's strict-language preconceptions against Haskell? I don't know. GHC provides a wealth of profiling tools that an expert Haskell user can employ to find space leaks. Heck, experts generally know where to look (excessive use of lists, spine-nonstrict data structures) so that the profiling tools become a last resort.
- whatshisface 9y agoA sufficiently smart [compiler | developer] can [make it so that | think] anything is easy. Since performance is exactly a measure of the number of imperative steps that need to happen in a program, low level imperative langauages are going to win in performance-obviousness every time. (Rust probably beating C in terms of avoiding memory problems, C probably beating rust in terms of not supporting language constructs that can make a single line worse than O(1).) "Accidentally" asking the language to do something time-expensive is as impossible in C as forgetting a free() in Haskell.
- JoshTriplett 9y agoI had the same experience: I really enjoyed the expressiveness and power of Haskell, as well as the strong type system. But Rust gives me all those things, as well as iterators for laziness when desired, without the pervasive laziness that had me constantly chasing down space leaks and adding strictness annotations.
- vmchale 9y ago>But Rust gives me all those things, as well as iterators for laziness when desired, without the pervasive laziness that had me constantly chasing down space leaks Well, yeah, Rust has manual memory management. Of course you don't get space leaks. Anyways, Rust's laziness is not on par with Haskell. Iterators are great but it's not at all the same as e.g. GHC's lazy IO.
- JoshTriplett 9y ago> Well, yeah, Rust has manual memory management. Of course you don't get space leaks. I wouldn't call Rust's memory management "manual". It's the only language I know of that I'd describe as having automatic memory management without garbage collection. > Anyways, Rust's laziness is not on par with Haskell. Iterators are great but it's not at all the same as e.g. GHC's lazy IO. Iterators, futures, and macros (for creating new language constructs) tend to provide the laziness I want. Beyond that, I've tended to find laziness as much a source of bugs as features. (Speaking from a perspective of having written and maintained large programs in Haskell, and in Rust.)
- agumonkey 9y agoHence a reason why so many people are sticking to ML despite the lack of social momentum.
- zem 9y agoocaml is a great language in its own right too; the only haskell features I find myself really missing are do notation and operator overloading.
- kornish 9y agoAlso the multicore concurrency.
- kornakiewicz 9y agoF# does have operator overloading.
- systems 9y agobut F# doesn't have Ocaml's performance, which I believe was the point being made for ML over Haskell I honestly don't know how F# compares to Haskell over performance
- bpicolo 9y agoF# is essentially just C#, which should be reasonably performant? It's possible the persistent data structures aren't optimized I guess? Pity something's busted in the benchmarks game: http://benchmarksgame.alioth.debian.org/u64q/fsharp.html http://benchmarksgame.alioth.debian.org/u64q/fsharp.html
- igouy 9y agoIt wasn't busted with .NET Core 1.0.1 005db40cd1. Is F# working with .NET Core 2.0 Preview 1 for you?
- wyager 9y agoThis is a very overstated concern, in my opinion. Based on my experience, once you learn the common gotchas (lazy folds, WHNF, etc.) it's rarely an issue. Real-world programs (web servers, databases, etc.) typically end up using frameworks that deal with strictness concerns for you anyway. For maybe the first couple weeks I was learning Haskell, this was a source of confusion, but I don't seem to run into it anymore. If it's really a struggle for some reason, you can always take the nuclear option and enable strict mode on your code. Haskell is very good for writing extremely fast code that's also extremely composable, which most languages (even Rust, to a substantial degree) really struggle with. Haskell's pure non-strict semantics and support for fusion/rewrite systems means that you can write complex operations on vectors, byte arrays, text, etc. that span multiple modules but get compiled down to extremely tight in-place assembly code. Another way of looking at it is that the economies of scale for Haskell are very different. There's a higher up-front cost because you have to learn about how strictness works, but as a consequence you can write vastly more complicated programs that are, say, 80% as fast as hand-optimized C for only 10% of the effort of hand-optimized C.
- delhanty 9y ago> .. you can write vastly more complicated programs that are, say, 80% as fast as hand-optimized C for only 10% of the effort of hand-optimized C. Computer Language Benchmarks of GHC versus C don't seem to be close to matching your 80% as fast claim [1]. Also, the 10% of the effort of hand-optimized C bit - seem to recall there was a caveat - "if you happen to Don Stewart" [2]. The following is just my vague, uninformed impression, but Haskell and Go seem to be opposite ends of a spectrum, with Rust somewhere in between: Haskell: good for expert individuals and small teams. The language is highly sophisticated and the compiler is rather slow. At heart, it's a research language, so the direction might not always suit production use. If you contract out to a Haskell development shop, who do you turn to with your Haskell code-base if things don't work out? Go: designed by Google for their use-case - large teams of commodity programmers. It's very quick to onboard programmers - they can be productive and non-dangerous quickly. The language is very simple and the compiler is very quick - which is again good for scaling large teams. [1] https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=ghc&lang2=gcc https://benchmarksgame.alioth.debian.org/u64q/compare.php?la... [2] https://donsbot.wordpress.com/2008/05/06/write-haskell-as-fast-as-c-exploiting-strictness-laziness-and-recursion/ https://donsbot.wordpress.com/2008/05/06/write-haskell-as-fa...
- hellofunk 9y agoI don't use Haskell but didn't I read recently that the latest version of Haskell addresses this common concern by allowing you to turn off laziness altogether so everything evaluates eagerly?
- lkurusa 9y agoThere is -XStrict, see here for a discussion: https://ghc.haskell.org/trac/ghc/wiki/StrictPragma https://ghc.haskell.org/trac/ghc/wiki/StrictPragma
- vmchale 9y ago>Haskell addresses this common concern by allowing you to turn off laziness altogether so everything evaluates eagerly It's a common concern but it's a terrible critique. Laziness has many subtle benefits, but everyone whines about it because its pitfalls are decidedly not subtle.
- deleted 9y ago[deleted]
- k__ 9y agoWasn't the selling point of laziness performance? "It only does what is needed!" I didn't use Haskell but Nix and at least there it seemed reasonable to "not do" everything.
- snovv_crash 9y agoIn other languages when the compiler misses an optimization you get a constant order penalty on a small piece of code. In Haskell when the compiler misses an optimization the performance hit is potentially unbounded, as it could think anything is a dependency. (You want the first N digits of pi? Just wait while I calculate all of them for you...)
- codygman 9y ago> You want the first N digits of pi? Just wait while I calculate all of them for you... I don't think that example cold actually happen, or at least I can't see how it would happen in Haskell.
- Tuna-Fish 9y agoHaskell can be made very fast. The problem is that at least for me, performance is often quite non-intuitive. As in, make tiny change to program, it is now a hundred times slower. Then you get to hunt down the reason why it's now doing too much work/ why stream fusion isn't working anymore/why it's leaking so much space/etc for hours. I enjoy writing Haskell for small hobby projects, but I doubt I would choose it for real work now that F# and Rust exist.
- tome 9y agoI don't think anything is the unique selling point of laziness. Wikipedia[1] says "The benefits of lazy evaluation include: * The ability to define control flow (structures) as abstractions instead of primitives. * The ability to define potentially infinite data structures. This allows for more straightforward implementation of some algorithms. * Performance increases by avoiding needless calculations, and error conditions in evaluating compound expressions." In my several-year experience as a professional Haskell developer the first and second points are at least an order of magnitude more important than the third. [1] https://en.wikipedia.org/wiki/Lazy_evaluation https://en.wikipedia.org/wiki/Lazy_evaluation
- georgewsinger 9y agoHaskell's laziness is an issue for you? Then how do strictness annotations (and/or module flags) not solve this problem? Haskell also has inline-C FFI support for "type safe" performance escape hatches (in the sense that you can manually bring C constructs into Haskell's type system): https://github.com/fpco/inline-c https://github.com/fpco/inline-c The only way that Haskell inescapably suffers from performance hits (that I'm aware of) is not in its laziness or lack of imperative programming support, but in its periodic GC pauses. In such cases where GC pauses are an issue, I still think you can -- in principle -- write more and more performance critical pieces of your application in a non-GC language (in fact, you could do this in Rust just as well as C/C++). You can also manually trigger a GC pass, although you cannot -- to my knowledge -- manually stop and start GC passes in your code. This is the approach I'm currently taking in a performance critical VR application where GC pauses could absolutely be an issue (using as much Haskell as possible, with C and GC triggers as an escape hatch). And if someone could point out a flaw in my reasoning (in particular, how GC pauses might be inevitably avoided even with C FFI), I would gladly pay them money, because it's so important I not get this one wrong :).
- mej10 9y agoIt is also possible to avoid GC pauses causing problems in your application with a load balancer. Basically shifting load between haskell processes when a big GC is imminent. Read about that technique from Simon Marlow of Facebook's Haskell team. Of course it would be awesome to not have to worry about that.
- georgewsinger 9y agoNice -- this technique never came up when I searched /r/haskell for GC pause workarounds. And yes -- it would be awesome not to have to worry about this.
- dllthomas 9y ago> Then how do strictness annotations (and/or module flags) not solve this problem? Strictness annotations (and associated pragmas) only change the strictness of constructors and functions defined in my modules. I still have to reason about laziness as I use almost anything from the Haskell ecosystem.
- brianberns 9y agoYou might want to consider F# as well. It supports both lazy and greedy functional programming very nicely.
- verandaguys_alt 9y agoWhile I've found that Haskell's laziness can often be worked around with appropriately-implemented memoization, it's an absolute PITA for anything that requires frequent hops into the IO monad (unsurprisingly). Historically, this has been a bottleneck for me that's prevented me from using Haskell in any major projects. A Haskell port of a logging library I'd originally written in Python ended up being almost 2 orders of magnitude slower than CPython 3, and almost 3 orders of magnitude slower than PyPy3. PyPy3 resulted in performance similar to a barely-optimized C port.
- vmchale 9y agoDo you have source code? It sounds like you were writing unidiomatic Haskell.
- verandaguys_alt 9y agoI actually posted the port on the Code Review SE, where (after almost a month of silence), someone stepped up and offered a CFFI solution. https://codereview.stackexchange.com/questions/157118/a-port-of-a-simple-logger https://codereview.stackexchange.com/questions/157118/a-port...
- vmchale 9y agoYou might have better luck with the fast-logger library, for one. I'd also suggest using ansi-wl-pprint, which would work on Windows and also probably be faster than string concatenation (which is just plain bad in Haskell). As was pointed out, GHC is calling getCurrentTime too often. If you take advantage of GHC's laziness, the value will stay valid longer. I assume that is what fast-logger does. https://hackage.haskell.org/package/fast-logger https://hackage.haskell.org/package/fast-logger
- crimsonalucard 9y agoIt's not just laziness. Functional programming is what happens to the universe when you eliminate the concept of Time. It is a mega abstraction over the what's really going on under the hood. However we live in the real world and in the real world you cannot eliminate the concept of time, even in an abstraction such as functional programming. Therefore Functional programming is an utter lie. Reasoning about the performance of a functional program is to peer through the lie and "reintroduce" time into this abstraction. This is why it it notoriously hard for functional programs to be reasoned about. Procedural programs are much more better for this in that regard.
- tome 9y agoThis is utter nonsense. Everything you wrote is somewhere between 90° and 180° wrong.
- crimsonalucard 9y agoI'm totally correct. You are completely unaware of what's going on. We can discuss this logically in the comments, you'll see. It's not going to pretty for you as my arguments will pick you apart piece by piece.
- hxegon 9y agosaying "I'm going to destroy your argument with logic" is not the same thing as actually destroying someone's argument with logic.
- crimsonalucard 9y agoLogically speaking, I never equated the two statements. It's up to him whether he wants to engage in a debate. Additionally, this guy just replied saying I was 180 degrees off angle without any explanation, how polite.
- akhilcacharya 9y ago>Functional programming is what happens to the universe when you eliminate the concept of Time. I've heard this a lot but still can't find a good code example to illustrate this. Any help?
- willtim 9y agoMost problems arise from using linked-lists in inappropriate situations. This includes using the default String type. Both the list and string syntax have been overloadable for a while, so using alternatives when necessary shouldn't be an issue. Understand the complexity of the data structure operations you are using and you will get fast code, laziness does not change this (although space usage can be hard to reason about). The benefits of laziness is difficult to appreciate if you are not used to it. For a great example of the benefits it brings, please read this: http://augustss.blogspot.co.uk/2011/05/more-points-for-lazy-evaluation-in.html http://augustss.blogspot.co.uk/2011/05/more-points-for-lazy-...
- vmchale 9y ago>It was very frustrating to try reasoning about performance in Haskell due to its laziness. Conversely, I find it hard to achieve the same performance with strict code. I think it's likely a matter of familiarity. >Haskell is notorious in my mind for being quite easy to write obscenely slow code in. The standard prelude is flawed in many ways. Haskell 2020 will hopefully fix this. In the meantime: the recursion-schemes library might be of great use.
- Symmetry 9y agoSomething I've always wondered about Haskell is whether there is, in practice, rope for the compiler to optimize things away from the theoretical underlying implementation. For instance a C compiler is free to turn for (int i = 0; i < N; i++) { a[i] = 2*b[i]; } for (int i = 0; i < N; i++) { c[i] = 2*d[i]; } into for (int i = 0; i < N; i+=2) { a[i] = 2*b[i]; a[i+1] = 2*b[i+1]; c[i] = 2*d[i]; c[i+1] = 2*d[i+1]; } It seems like GHC ought to similarly be able to turn some foo :: [Int] -> [Int] into foo :: [(Int, Int)] -> [(Int, Int)] under the covers for a similar speedup as long as it can, as with the C compiler, handle the case of an odd length with a bit of extra code. There are limits to how much you can restructure a list that's exported outside the compilation unit (my Haskell knowledge is fuzzy here so that's probably not the right terminology). And if the list is being re-stitched in odd ways it might be a bad idea. But as far as I can tell it ought to be doable and useful in most common cases. Of course maybe it's already doing this in those cases where it can prove that it works and that's why Haskell performance generally is good but fragile.
- haldean 9y agoHaskell performs a very cool optimization called "stream fusion" to deal with a whole class of traversal optimization problems; stream fusion removes intermediate list results completely, and bundles a bunch of things that look like maps/reduces/filters into a single operation. Your example doesn't quite hit it, but a similar bit of code like: for (int i = 0; i < N; i++) a[i] = 2 * b[i]; for (int i = 0; i < N; i++) c[i] = 2 * a[i] + b[i]; t = 0; for (int i = 0; i < N; i++) if (b[i] % 2 == 0) t += c[i]; Would be rewritten to the equivalent of: t = 0; for (int i = 0; i < N; i++) if (b[i] % 2 == 0) t += 5 * b[i]; Lots more info on the GHC optimizations page: https://wiki.haskell.org/GHC_optimisations#Fusion https://wiki.haskell.org/GHC_optimisations#Fusion
- Symmetry 9y agoYes, stream fusion is super nifty. But can Haskell alter the size of the chunks it's sending through the stream? There was a recent HN thread about how GNU 'yes' is so fast thanks to buffering. Obviously too large a buffer would blow out the cache and stream fusion avoids that but a moderate amount of buffering so that you're neither working array by array nor element by element but cachable chunk by cachable chunk should be a happy middle. And with Haskell lists reduce pointer chasing as well.
- Gackle_Murderer 9y agoYou might like Idris. Not nearly as mature as Haskell, but definitely as powerful, with much more reasonability when it comes to performance, thanks to eager evaluation.
- yitzg 9y agoAs a Haskell practitioner in industry - for several years we have been creating technical documentation sites for large enterprise customers, providing fast semantic search for gigabytes of content serving millions of users - I can attest that this simply isn't true. We have found that reasoning about performance in a pure functional language is not harder than for any other kind of mainstream language. Except in the sense that it is different, so not all of your skills and intuition from other languages necessarily apply.
- thesz 9y agoSomething I found about going to Haskell from <any other language> is that Haskell provides many powerful abstractions without compromising on performance. Especially programmer's performance. If you do not need to write notoriously slow code in Haskell, just don't do it. Use libraries (containers and mtl especially great), keep state strict (a handful of bang patterns). I use Haskell's laziness with great success (look for paper "generating power of lazy semantics" it's fascinating; look "the essence of functional programming" for even more fascination). I use Haskell's flexibility with great success (how about beating C speed ten times? how about parallelization to all cores with couple lines of code?). It is really great language. BTW, Haskell's RTS reuse chunk type field which is needed for implementation of laziness for synchronization and it is great! This means that it can provide everything that Java and/or .Net provides and get away with twice as less overhead for it.
- spullara 9y agoMaybe the other way around.
- asdfaoeu 9y ago"the legacy C++" Interesting reading but the author seems intent on pushing some buttons.
- pjmlp 9y ago> More advanced type systems, however, allow to specify the generic constraints explicitly. Well, Java allows it, even if it looks a bit unglier than the Rust example. <T extends Comparable<T>> T min (T a, T b) { if (a.compareTo(b) > 0) { return b; } else { return a; } } And even without general availability of concepts (already in gcc 6.x), one can achieve it in C++ via if constrexpr.
- DaiPlusPlus 9y agoThe difference with Rust is that you can apply a trait to an extant type you don't "own" - you can't do that in Java or C#: you would need to use the decorator-pattern (boilerplate ahoy!). C++'s checks are closer to duck-typing in practice.
- pjmlp 9y agoI agree with you in regard to Java and C#, not so much regarding C++, because GCC already supports concepts since version 6.0, with other compilers adding support for them as part of the validation work to have them finally on ANSI C++20 standard. In any case, regardless of the fine grain details, all of them allow for to "specify the generic constraints explicitly.".
- louthy 9y agoActually you can do ad-hoc polymorphism in C# (and I assume Java too, although I've not used it). Here's an example of implementing an Eq and Ord 'type class' in C#, with 'class instances' of OrdInt and OrdString. Then a simple generic bubble-sort function which works on any type that has an Ord instance: public interface Eq<A> { bool Equals(A x, A y); } public interface Ord<A> : Eq<A> { bool GreaterThan(A x, A y); bool GreaterThanOrEq(A x, A y); bool LessThan(A x, A y); bool LessThanOrEq(A x, A y); } public struct OrdInt : Ord<int> { public bool Equals(int x, int y) => x == y; public bool GreaterThan(int x, int y) => x > y; public bool GreaterThanOrEq(int x, int y) => x >= y; public bool LessThan(int x, int y) => x < y; public bool LessThanOrEq(int x, int y) => x <= y; } public struct OrdString : Ord<string> { public bool Equals(string x, string y) => x == y; public bool GreaterThan(string x, string y) => x.CompareTo(y) > 0; public bool GreaterThanOrEq(string x, string y) => x.CompareTo(y) >= 0; public bool LessThan(string x, string y) => x.CompareTo(y) < 0; public bool LessThanOrEq(string x, string y) => x.CompareTo(y) <= 0; } public static class Testing { public static void Test() { var x = new[] { 3, 8, 1, 2, 10 }; var y = new[] { "mary", "had", "a", "little", "lamb" }; BubbleSort<OrdInt, int>(x); BubbleSort<OrdString, string>(y); } public static void BubbleSort<OrdA, A>(A[] values) where OrdA : struct, Ord<A> { bool swap; do { swap = false; for (var i = 0; i < values.Length - 1; i++) { var x = values[i]; var y = values[i + 1]; if (default(OrdA).GreaterThan(x, y)) // Ad-hoc polymorphic call to GreaterThan { swap = true; values[i] = y; values[i + 1] = x; } } } while (swap); } }
- partycoder 9y agoRust still allows imperative programming whereas Haskell doesn't. This makes a big difference. Rust is closer to Alan Turing than it is to Alonzo Church.
- wyager 9y agoHaskell allows you to recreate standard imperative semantics purely (with the State monad, plus lenses for familiar syntax), or to use actual stateful imperative mutability ("purely" via ST or impurely via IO).
- danidiaz 9y agoThere was a recent post about "imperative Haskell": http://vaibhavsagar.com/blog/2017/05/29/imperative-haskell/ http://vaibhavsagar.com/blog/2017/05/29/imperative-haskell/ The code in this other post about implementing string distance metrics is also quite imperative: https://markkarpov.com/post/migrating-text-metrics.html https://markkarpov.com/post/migrating-text-metrics.html
- xedrac 9y agoHaskell definitely allows imperative programming, it's just not particularly good at it.
- eklavya 9y agoWhat is it lacking for imperative programming? I find it to be immensely good at it!
- pathsjs 9y agoDon't know... mutable collections? A way to make sure things are evaluated without writing seq every other line?
- Tarean 9y agoMutable hashtables: https://hackage.haskell.org/package/hashtables https://hackage.haskell.org/package/hashtables Mutable arrays: https://hackage.haskell.org/package/vector-0.12.0.1/docs/Data-Vector-Mutable.html https://hackage.haskell.org/package/vector-0.12.0.1/docs/Dat... Strict by default: Put {#- Language Strict #-} at the top of files where necessary but usually you'd just use bangpatterns and unbox-strict-fields.
- vesak 9y agoI wonder if Idris could some day take Haskell's place. It sports default eager evaluation. Seems like the tooling (package managers etc.) isn't quite there yet, though.
- runeks 9y agoIs a difference in a default option really enough for a language to take the place of another? And if it's not just a change in a default option, but the removal of laziness, we lose something, which will make the choice less obvious. I think it's more likely that, if dependent types prove really useful, Haskell will adopt these, and people will adapt their code, rather than port everything to a new language. As far as I can see, Idris is too much like Haskell to take its place. Porting thousands of libraries to a new language is a huge effort, so a huge advantage is required, which I don't see Idris offering.
- firethief 9y agoA System F type system can't be replaced by a dependent type system without affecting existing code. There is no way to turn the libraries in Haskell into libraries in dependently-typed Haskell without "porting them to a new language" and all the work that entails.
- taktoa 9y agoThis is 100% false. The Calculus of Constructions is a superset of System F. You may be thinking of the fact that if you want your type system to be sound when interpreted as a logic, then termination must be guaranteed (which would break backwards compatibility). Dependent types and totality are often found together, but are in actuality orthogonal features.
- vesak 9y ago>And if it's not just a change in a default option, but the removal of laziness, we lose something, which will make the choice less obvious. What would we exactly lose? >As far as I can see, Idris is too much like Haskell to take its place. Porting thousands of libraries to a new language is a huge effort, so a huge advantage is required, which I don't see Idris offering. That is true, though. Perhaps Rust is the safer bet, even if it lacks many nice things. The sum is probably quite a lot better still.
- toprerules 9y agoThe similarities are striking. Both have a problem with undocumented or experimental modules for everyday tasks, both use compiler plugins to make sure that every package is using its own superset of the language (although in Rust this only applies to nightly), both tout lofty goals while rarely producing production grade systems. Rust is the first toe dip into the world of blog posts heralding the"coming of the age of reason" when we all see the error of our ways for writing dangling pointer references and impure functions. To be a complete cynic, I hope Rust runs right away from over generalized abstractions and the Haskell indifference to achieving real success by overcomplicting even the most mundane of problems.
- Profragile 9y agoHaskell and Clojure are two languages I really hope I never have to program in. Seriously fuck them. I will program in the worst languages if only to just not be associated with those people. I have written a few small programs in Rust, but if it attracts the same kind of people, I'll happily move away.
- motet_a 9y agoYes. Complex languages are not required to solve complex problems. This is why Go and JavaScript are so popular.
- Sharlin 9y agoI'd say neither Go nor JavaScript are predominantly used to solve complex problems. The main use cases for both are solving mundane problems by mundane programmers. In case of Go that's an explicit design philosophy.
- vmchale 9y agoThat's... not really true. JavaScript solves trivial problems, and it's mainly popular because it's literally the only web language around.
- jnordwick 9y agoAlthough clearly presented to push some buttons, it isn't completely wrong. Am upvote hoping you don't get buried.
- le0n 9y agoHaskell/GHC will soon have an extension for linear types, which will bring the languages much closer: http://blog.tweag.io/posts/2017-03-13-linear-types.html http://blog.tweag.io/posts/2017-03-13-linear-types.html
- kccqzy 9y agoYeah right. If only the standard library (the base package) could immediately be converted to use linear types and we can all benefit from that! (Hint: it won't. Even the fairly no-brainer AMP and BBP took an absurdly long time. This is extremely slow by Rust standards. The Haskell community might, but the stewards of the standard libraries don't have the move-fast-and-break-things attitude.)
- Tarean 9y agoDid rust ever have a large scale breaking change? Anyway, the linear type proposal is designed to be completely backwards compatible so that shouldn't be as big of an issue.
- kccqzy 9y agoYes I know it's completely backwards compatible. But in practice if the standard libraries don't change, (a) there won't be a ready source of inspiration and examples to copy from; (b) actually the feature is really geared more towards libraries than applications, so it's less useful if the base library doesn't adopt it wholeheartedly.
- Tarean 9y agoFair enough, although it would be easy to have an alternative prelude with linear types that libraries could depend on. Just that the extra dependency would really suck. Haven't sunk a lot of time into it yet to be honest, I think the biggest beneficiaries will be streaming libraries and non-gced data structures like long lived queues?
- steveklabnik 9y ago
- sandGorgon 9y agoI have heard the same thing about Kotlin now - https://hackernoon.com/kotlin-functors-applicatives-and-monads-in-pictures-part-1-3-c47a1b1ce251 https://hackernoon.com/kotlin-functors-applicatives-and-mona...
- throwaway91111 9y agoErr kotlin as a gateway drug to haskell? They might wanna fix type erasure first....
- decafbad 9y agoRust and Kotlin destroy any previous claims about practical usages of Haskell.
- jmcomets 9y agoCould you elaborate? I'm not sure practical usages of Haskell are replaced by Rust/Kotlin, the high-level of abstraction and pure functional paradigm are practical.
- kryptiskt 9y agoKotlin isn't anywhere near being a substitute for Haskell, it's a nice set of syntactical tweaks for Java users but it doesn't even have ADTs or real pattern matching.
- lmm 9y agoLanguages without HKT are horribly impractical for large codebases.
- pathsjs 9y agoYet there are not many large codebases in languages with HKT, and even those which are there (mainly big Scala projects) do not use HKT
- lmm 9y agoMost large codebases are terrible, and these facts are not unrelated.
- AnimalMuppet 9y agoI could be wrong, but I don't think that there are enough large codebases that use HKT for us to be able to know whether most large codebases that use HKT are not terrible. I suspect that it is closer to the truth to say that most large codebases are terrible, regardless of language, and that HKT won't save you. (Using HKT may help, some. Using HTK well may help more. But the problem with large codebases is that enough programmers work on it that the talent level tends toward the average of the universe of programmers. That's... not good. It means that whatever tool or technique you choose won't be used well.)
- deavmi 9y agoThen go to functional rehab.
- v0lta 9y agoThat's the most HN post title in a while
- ucaetano 9y agoThe Rust Evangelism Strike Force is back!
- sctb 9y agoComments like these are insidious on Hacker News because they're at once inflammatory and deathly boring. Please don't post like this again. https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html
- timwaagh 9y agoi imagine they both provide a similar hipster code high. while being fairly hard to do something useful in or make money with.
- allengeorge 9y agoThe article references using trait objects for dynamic dispatch. FWIW, I found them extremely limited: you can't use generics, can't return Self... I wonder how often people use them.
- cbcoutinho 9y agoWhat do you mean you can't return self? I'm just starting out with learning rust, but from what I've gathered you can use objects in a myriad of ways that will allow you do what you need. Instead of returning self, you could just pass a reference - you need to mutate self then just pass a mutable reference. Did I miss something here?
- steveklabnik 9y agoReturning Self in a trait object isn't possible; it's not object safe. In order to return Self, you'd need to know the concrete type of the thing, and when you have a trait object, that's erased. Returning a trait object instead of plain Self would work though.
- kbutler 9y agoIsn't the most significant line: "For work-related reasons, I had to recently get up to speed on programming in Haskell"? I was somewhat disappointed not to have a followup to what work-related reasons there might be. Note also that the About page says "work at Facebook".
- dllthomas 9y agoIf you're puzzling at the connection between Facebook and Haskell, https://github.com/facebook/Haxl https://github.com/facebook/Haxl is the most obvious one.
- leshow 9y agoI have found them to be very similar too. I started learning Haskell in earnest last September, following along with the exceptional "Haskell: First Principles" which I highly recommend. I had been toying with Rust around this time and I found a confluence of ideas between the two languages. Most things I learned in Haskell I was able to carry over to Rust. The inverse was not quite as true. But I still love Rust. Any time I need something performant, or I just want to play around, it's my first choice.