5 ms·
I’d love to see comparison between Rust and Haskell/ML WRT polymorphism. I wonder if “gets right” would appear there and on what side.
by myst 9y ago
I’d love to see comparison between Rust and Haskell/ML WRT polymorphism. I wonder if “gets right” would appear there and on what side.
- jmcomets 9y agoApples & Oranges. Although Rust heavily borrows from the ML family, the fact it has mutability and imperative reasoning makes it hard to compare them. But if you want a short one: - Sum Types EDIT: AND Product Types (silly me) - function-objects & closures - typeclasses (as far as I can tell), but no higher kinded types - no monads, functors nor monoids built-in - trait objects (eg. runtime polymorphism, think "abstract classes")
- ketralnis 9y ago> - Sum Types but no Product Types Maybe I'm missing something, but aren't tuples and structs/records examples of product types? Which both rust and haskell have?
- mathw 9y agoYes I always thought tuples were the archetypal product type, which is why in some ML dialects they're notated as "Type1 * Type2". Rust most certainly has them, as does Haskell. Records/structs of course are just the same thing with names for the components. Thus, even Java has product types.
- masklinn 9y ago> Thus, even Java has product types. Even C has product types. Which is why I'm always bothered when people claim language X lacks algebraic data types. They probably lack sum types, but are very unlikely to lack product types.
- beojan 9y agoC also has sum types with unions (though without any indication of which of the alternatives is actually present).
- red75prime 9y agoThey are mix types then.
- kod 9y agoProduct types without sum types and pattern matching are basically useless for expressing ADTs. That's what people mean.
- masklinn 9y ago> Product types without sum types and pattern matching are basically useless for expressing ADTs. That makes no sense. Algebraic data types are not expressed, they're a concrete thing, a classification of composite types (by multiplication (hence product types) or addition (hence sum types)).
- kod 9y agoSure it does, languages allow you to express things. Some shitty languages don't have a concise way for you to express particular things (like sum types), so you have to rely on idioms or "patterns".
- kornish 9y agoOh wow, never realized the connection between product types and the ML type notation. Thanks for the insight!
- jmcomets 9y agoThanks for the insight on this, I've edited my response. Are there any extra features in Haskell with product types? I've always understood that there was better composition support for product types in Haskell
- bjz_ 9y agoNot really. Haskell has support for higher kinded types that allow it to support lenses, which are a powerful way of declaratively traversing through data structures, so perhaps that's what you mean. On the other hand Haskell's record support is pretty woeful in comparison to languages like Ocaml, Elm, and Purescript that have support for row polymorphism. Depending on the sophistication of their implementation, row polymorphism will allow you to add and remove fields from records in a statically type checked way, and some may even allow you to pass labels around at the type level. They can even be used to model extensible variants and extensible effect types. There are creative ways to encode this in Haskell, but they all have their drawbacks, can be painful to work with, and really don't feel like a natural part of the language.
- kazagistar 9y agoWell, there is per-field lazyness (with the ability to opt out). So product types can let each consumer choose which parts of the result to actually evaluate and discard the rest.
- bjz_ 9y agoAnd in SML tuples are just records with numeric fields in a special order. Enter this in the repl: { 1 = "hi", 2 = "howdy" }; And get: val it = ("hi","howdy") : string * string
- MHordecki 9y agoThere are other imperative languages in the ML family too, right? OCaml has an imperative mode. I don't think Rust is that much different from other functional languages. The main critical difference is the manual memory management feature - the way it's acknowledged and used throughout the language and the ecosystem means that the functional patterns commonly used in garbage collected languages don't look nearly as natural in Rust.
- axlprose 9y agoHere's a post that compares the two pretty well, though it assumes you know a bit of some ML-style language: http://science.raphael.poss.name/rust-for-functional-programmers.html http://science.raphael.poss.name/rust-for-functional-program...
- jmite 9y agoRust's traits are basically Haskell typeclasses, with a few extensions enabled, like multiple parameters. Trait objects are basically existential types, with a few more restrictions on them. But in essence polymorphism in Haskell and Rust are very similar. The big thing Rust is missing is higher kinded polymorphism, ie the ability to abstract over type constructors. This makes it easy, for example, to abstract over a container type while putting different things in that container. This has get approved in the Associated Type Constructors RFC, but it's still in the works for actually landing.
- moomin 9y agoOne thing no-one else has mentioned yet: in Haskell you can’t provide a specialised implementation of a generic function. In Rust you can. Whilst this is obviously useful, it makes it impossible to perform parametricity type-based reasonbig.
- domlebo70 9y agoI think you can using GHC Pragmas.
- hiker 9y agoOf course you can. The good old {-# LANGUAGE OverlappingInstances #-}.
- jeremyjh 9y agoIn Haskell you have to supply the entire instance, versus just specializing one method as you can do in Rust. Also in Haskell this extension is not recommended for general use and you won’t often find specialization like this in the wild.
- ves 9y agoThe typical way to do multiple instances for a given type is with trivial newtype wrappers for each instance. See the "Sum" and "Product" monoid instances (although these wrappers are also necessary for instance decidability). This is fine "in the wild." Also, I'm not sure why you would ever want a "partial instance," as it would mean that your program could be unsafe but still typecheck (I haven't checked out Rust's implementation or motivation). Just use more specific classes, and you can even use a "generic" "instances of the components imply an instance of the whole" class and instance.