5 ms·
My biggest observation from switching from Haskell to Rust is the change in thinking in terms of program composition. In Rust you need to really make some care
by sfvisser 4y ago
My biggest observation from switching from Haskell to Rust is the change in thinking in terms of program composition.
In Rust you need to really make some careful design choices in your producer/library code depending on the expected use. All of them quite on the operational level and not really semantically. So many internal choices about refs/arcs/pins/mut/ownership leak out.
In Haskell you don’t really do that. If your library internals are neatly written combinators with the right type and semantics you can just expose them and you’re done. Like the article explains, laziness is a big part of this.
I understand where that difference comes from, but it’s really a very different way of thinking.
- asplake 4y agoHow much of that do you think is due to laziness specifically and not GC?
- sfvisser 4y agoYes, the GC helps tremendously here of course. I guess laziness helps mostly by not dictating the granularity in which to expose both data and building blocks. You can expose more than strictly needed and consumers just pick what’s relevant. Keeping APIs simple and to the point.
- wirrbel 4y agoI really wished there was a GC-ed but strictly-evaluating Haskell. A Rust-like syntax would probably help with adoption but I don't have a strong preference in that.
- discarded1023 4y agoTry Standard ML or ocaml. You may be surprised how far the module system can take you, and how limited type classes really are for expressing abstractions. On a different vector, you can see the same story -- type classes are convenient but too limited -- in the development of abstract algebra/topology/analysis/... in Isabelle/HOL. As for laziness, things don't work out too well for a variety of reasons. Bob Harper laid out several many years ago. See e.g. https://news.ycombinator.com/from?site=existentialtype.wordpress.com&next=2481042 https://news.ycombinator.com/from?site=existentialtype.wordp...
- wirrbel 4y agoI really like standard ML. Modules are great but type classes would be … more pragmatic?
- bmitc 4y agoMy preference are ML dialects, but it sounds like Idris is something you should check out. It's strict by default and has type classes and dependent types.
- wirrbel 4y agoIdris was always filed in my head as some estoric/academic/obscure thing, will have a look at it.
- bmitc 4y agoI actually think it's probably less academic than Haskell or Racket. It's intended to be a practical language that people build things with. It just has an advanced type system and a small community.
- erk__ 4y agoThere is even a SML that does not use a GC* but instead does "region based" memory mangement. https://elsman.com/mlkit/about https://elsman.com/mlkit/about *most of the time.
- one-punch 4y ago> I really wished there was a GC-ed but strictly-evaluating Haskell. To answer this question literally, there are PureScript (transpile to JavaScript), Idris (dependently typed), OCaml, and Standard ML (as discarded1023 pointed out). But I think the wish for a strictly-evaluating Haskell is sometimes in fact a wish for a Haskell with more predictable performance (especially in memory usage). If so, the Linear Type/Arrow of recent GHC may fit the bill [1]. My wish is for Haskell to have a better runtime [2] with optimal reductions (with more predictable performance and without GC) [3], which could have Rust-like performance without lifetimes, while being lazy. [1]: https://www.tweag.io/blog/2017-03-13-linear-types/ https://www.tweag.io/blog/2017-03-13-linear-types/ [2]: https://discourse.haskell.org/t/high-order-virtual-machine-hvm-an-optional-ghc-like-runtime-for-rust-with-many-comparisons-to-ghc/4118 https://discourse.haskell.org/t/high-order-virtual-machine-h... [3]: https://github.com/HigherOrderCO/HVM https://github.com/HigherOrderCO/HVM
- noloblo 4y agoAnd faster Compile times haskell compile times relative to golang are super slow
- one-punch 4y agoGolang prioritizes compile time (hence it took them so long to get Generics), which Rust and Haskell are unlikely to beat, as they both prioritize high-levels of abstractions (more compile time for zero cost abstractions at runtime). That said, since GHC is implemented in Haskell, the compile time will likely improve if linear type/arrow, or a better runtime (such as optimal reductions), is used by GHC itself.
- noloblo 4y agowhat is linear type/arrow?
- one-punch 4y agoLinear Type/Arrow makes sure values are consumed exactly once (as they cannot be duplicated nor destroyed), and such runtime can be used for efficient resource management without reference counting or garbage collection [1]. For Linear Type/Arrow in Haskell, see [2][3][4]. For Linear Type (or Relevant Type) in Rust, see [5]. [1]: https://news.ycombinator.com/item?id=16100840 https://news.ycombinator.com/item?id=16100840 "Linear types can change the world" [2]: https://www.tweag.io/blog/2017-03-13-linear-types/ https://www.tweag.io/blog/2017-03-13-linear-types/ "Linear types make performance more predictable" [3]: https://www.tweag.io/blog/2023-01-26-linear-constraints-freeze/ https://www.tweag.io/blog/2023-01-26-linear-constraints-free... "Linear Constraints: the problem with O(1) freeze" [4]: https://www.reddit.com/r/haskell/comments/v3gouc/linear_text_builder_up_to_20x_faster_than/ https://www.reddit.com/r/haskell/comments/v3gouc/linear_text... "Linear Text Builder: up to 20x faster than alternatives" [5]: https://faultlore.com/blah/linear-rust/ https://faultlore.com/blah/linear-rust/ "The Pain Of Real Linear Types in Rust"
- deleted 4y ago[deleted]
- xmcqdpt2 4y agoScala can be quite Haskell-like and is eager evaluating by default. (It's a lot less opinionated though so you can use it to write Java like code.)
- wirrbel 4y agoI have worked professionally with Scala for two years and while I see its appeal of using it over plain Java, it always felt fairly alien to me and pretty complex (probably due to the Java interop and strong typing).
- bmitc 4y ago> Like the article explains, laziness is a big part of this. I don't think the article does a good job addressing this. They have a conclusion they want to get to, but I don't see how they get there with the arguments provided. Languages that are eager by default but support lazy evaluation are also not really discussed, and it's because they are the best of both worlds. Yes, lazy evaluation has its pluses, but more often than not, you don't need it. So it's better to have optional lazy evaluation and then reach for it when you really need it. F#, OCaml, Racket, Elixir, etc. work this way. And F# and Elixir, especially, heavily use compositional code with pipelines. The article states: > On a strict FP language, you end up writing more explicitly recursive functions (hopefully with tail calls) than using higher order functions that express your intent. That is not my experience at all, and I haven't seen anything that supports that. Lastly, Idris has a short FAQ as to why it's eager by default: https://docs.idris-lang.org/en/v1.3.4/faq/faq.html#why-does-idris-use-eager-evaluation-rather-than-lazy https://docs.idris-lang.org/en/v1.3.4/faq/faq.html#why-does-... And that addresses something else the article doesn't get at. Preciseness and explicitness make code much easier to reason about. Lazy evaluation increases mental burden.
- sfvisser 4y ago> Lazy evaluation increases mental burden. In some situations, definitely! In other situations, definitely not! My experience with writing Haskell application code is that you’re thinking way less about the runtime operational aspect of your code than in any other language. The burden is much lower. The exceptions are possibly when writing low level library code that involves a lot of IO and steaming. Or when storing a lot of data in-memory for longer periods of time.
- runeks 4y ago> Languages that are eager by default but support lazy evaluation are also not really discussed, and it's because they are the best of both worlds. Yes, lazy evaluation has its pluses, but more often than not, you don't need it. What makes you say strictness is the right default? I write Haskell at my day job, and I practically never experience crashes due to space leaks. And given that strictness has its own performance issues (unnecessary evaluation), it’s not clear to me that either is the “right” default.
- amelius 4y agoIt would be great if the language allowed you to defer choices and program like in Haskell and then add constraints later and end up with the advantages of Rust. Or apply a series of correctness preserving transformations (perhaps GPT can help with that).