Live data from Hacker News

Rust as a gateway drug to Haskell

xion.io

151–160 of 218 posts

Re: Rust as a gateway drug to Haskell

#151

Earlier quoted context omitted.

Something 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 into for (int i = 0; i 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 l…

Haskell 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 Would be rewritten to the equivalent of: t = 0; for (int…

Yes, 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.

Re: Rust as a gateway drug to Haskell

#152
post #39

Earlier quoted context omitted.

The 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.

Actually 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 { bool Equals(A x, A y); } public interface Ord : Eq { bool GreaterThan(A x, A y); bool Great…

But you just proved my point: your OrdString and OrdInt types there are implementations of the Decorator pattern (just using interfaces instead of superclasses).

Re: Rust as a gateway drug to Haskell

#153
post #149

Earlier quoted context omitted.

I'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.

saying "I'm going to destroy your argument with logic" is not the same thing as actually destroying someone's argument with logic.

Logically 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.

Re: Rust as a gateway drug to Haskell

#154

Earlier quoted context omitted.

Haskell 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 Would be rewritten to the equivalent of: t = 0; for (int…

Yes, 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 s…

I think that the issue you're describing about `yes` was around building a buffer and issuing one big write() syscall instead of a bunch of small ones. I'm not sure about the actual implementation of the IO monad, and whether or not it coalesces call to write(), but it would definitely be possible. Also, idiomatic Haskell would make large writes, because usually (at least in my experience) you create a large string/Text representing your output, and then putStrLn or print it all at once.

In regards to assembling the stream: when the list is actually materialized, I assume it's done one element at a time, but the LLVM backend that GHC uses might be doing some loop unrolling, but I'm not sure.

Stream fusion doesn't require that all of the streams be the same type, though! Elements at different points in the stream can have wildly different sizes. For example, this would be fused:

    sum . map length . map double $ ["hello", "Symmetry"]
        where double x = concat [x x]
That will never materialize a list of Strings, even though at two points in the stream you had a stream of strings.

Re: Rust as a gateway drug to Haskell

#155

Earlier quoted context omitted.

F# does have operator overloading.

but 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

F# 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

Re: Rust as a gateway drug to Haskell

#156

Something 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.

You 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.

Re: Rust as a gateway drug to Haskell

#157
post #16

Earlier quoted context omitted.

This 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.…

> .. 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, uninfor…

> commodity programmers

Heh

Re: Rust as a gateway drug to Haskell

#158

I have heard the same thing about Kotlin now - https://hackernoon.com/kotlin-functors-applicatives-and-mona...

Err kotlin as a gateway drug to haskell? They might wanna fix type erasure first....

maybe kotlin as a gateway drug to scala as a gateway drug to haskell

Re: Rust as a gateway drug to Haskell

#159
post #39

Earlier quoted context omitted.

Actually 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 { bool Equals(A x, A y); } public interface Ord : Eq { bool GreaterThan(A x, A y); bool Great…

But you just proved my point: your OrdString and OrdInt types there are implementations of the Decorator pattern (just using interfaces instead of superclasses).

No they're not, they are not wrapping an object instance, they are providing ad-hoc functionality only. The generic parameters provided to BubbleSort are constraining the arguments and allowing access to the ad-hoc functionality, something that can't be done with inheritance unless you own the type.

This is exactly how traits, implicits, type-classes, class-instances, and concepts work in other languages like Scala, Haskell, etc.

Re: Rust as a gateway drug to Haskell

#160
post #64

Earlier quoted context omitted.

Some people also complain about a tiny set of syntactic issues. Other than that I like both ml and ocaml.

But that's what most devs do, right? If it doesn't look like C it's ugly, haha. Anyway, Reason seems to have a bit nicer syntax than OCaml, I think.

Reason seeks to destandardize syntax, a fascinating experiment I'd prefer to watch in a language not already held back by community fragmentation.
Post reply on HN