5 ms·
> Correction: Haskell has them, Rust has a limited form of them, and Scala encodes them using a horrible hack. Fun fact: The way Haskell encodes them is identi
by frowaway001 13y ago
> Correction: Haskell has them, Rust has a limited form of them, and Scala encodes them using a horrible hack.
Fun fact: The way Haskell encodes them is identical to the way Scala does.
> What you lose is compiler-enforced coherence. When you use type classes, certain functions come with the expectation that you will consistently pass the same dictionary around between calls.
Could you please show an example where this goes wrong?
> With actual type classes, this is a given: there can be at most one instance of a type class for a type (or tuple of types). With Scala's implicits, you can trick the compiler into passing different dictionaries between two calls that expect the same dictionary.
Limiting type classes to one instance per type ... that's what I would call completely pointless. With that kind of restriction, why have typeclasses in the first place? There is probably not much (anything?) which could be enabled by such a crippled feature compared to dynamic dispatch/OO/subtyping.
> I am aware that this is a tradeoff: Haskell's type classes are antimodular (because a global set of instances must be kept in order to guarantee instance uniqueness per type) and Scala's implicits can be used in potentially incoherent ways.
Can you provide an example?
- catnaroek 13y ago> Fun fact: The way Haskell encodes them is identical to the way Scala does. No. The way Haskell does type classes ensures coherence: you can never pass the "wrong" dictionary. There is at most one dictionary per type, globally, so it is always the right one. > Limiting type classes to one instance per type ... that's what I would call completely pointless. Ensuring instance coherence is not pointless. It helps in the correctness department. > With that kind of restriction, why have typeclasses in the first place? There is probably not much (anything?) which could be enabled by such a crippled feature compared to dynamic dispatch/OO/subtyping. Wrong. > Can you provide an example? http://ideone.com/L0yYfC http://ideone.com/L0yYfC -- This abomination would not have happened in Haskell.
- frowaway001 13y ago>> Fun fact: The way Haskell encodes them is identical to the way Scala does. > No. The way Haskell does type classes ensures coherence [...] No one is disputing that Haskell layers additional restrictions on top of typeclasses, but as mentioned the encoding is the same in Haskell and Scala (look it up if you don't believe me). That's why it's kind of funny that you think Scala's encoding is terrible. > Wrong. I guess that's why all those GHC extensions to make Haskell's typeclasses less half-assed exist in the first place? :-) > This abomination would not have happened in Haskell. What abomination? This code does exactly what you told it to do. It tells us more about your inability to write code which doesn't look like a terrible translation of Haskell. If you wanted the ordering to be a property of your type, then make it a property. But don't whine if you write code which lets you switch typeclass instances that it in fact let's you switch typeclass instances. :-)
- catnaroek 13y ago> No one is disputing that Haskell layers additional restrictions on top of typeclasses The definition of "type class" requires that there can be at most one instance per type. I know perfectly well that, operationally, Haskell just passes a dictionary around just like in Scala. But, denotationally, instance uniqueness causes a difference in semantics, namely, guaranteed coherence. And, to be frank, one of the reasons why I have adopted functional programming is that, most of the time, I do not want to be slowed down by operational concerns. Haskell allows me to write code I can reason about in an equational fashion. Scala does not. > I guess that's why all those GHC extensions to make Haskell's typeclasses less half-assed exist in the first place? :-) I was talking about Haskell, not GHC. Personally, when it comes to GHC's type system extensions, I am rather conservative: MultiParamTypeClasses, FunctionalDependencies, GADTs, TypeFamilies (only for associated families, never for "free-floating" families), RankNTypes. (That is, I may use other extensions, like OverloadedStrings, but they are not extensions of the type system itself.) As I said above in this thread (though not in reply to you), I find antimodularity (due to instance uniqueness) annoying, but incorrectness freaking scary. Of course I would rather have both modularity and guaranteed coherence, but if one must absolutely go away, then it is modularity. > What abomination? (...) If you wanted the ordering to be a property of your type, then make it a property. I want the language to help me write correct code, and implicits do not help.
- frowaway001 13y ago> Haskell allows me to write code I can reason about in an equational fashion. Scala does not. That's just non-sense. In Scala typeclass instances are just part of the equation. That's just not a big deal at all. > Personally, when it comes to GHC's type system extensions, I am rather conservative: MultiParamTypeClasses, FunctionalDependencies, GADTs, TypeFamilies (only for associated families, never for "free-floating" families), RankNTypes. LOL. I guess that's a joke, right? > I find antimodularity (due to instance uniqueness) annoying, but incorrectness freaking scary. There is no incorrectness. The code you have written does exactly what you have specified. Don't blame the tools for writing bad code. :-) Haskell providing you the tools to easily corrupt your runtime, now that's what I call "freaking scary incorrectness". > I want the language to help me write correct code, and implicits do not help. Then why do you fight the language so much in your code example? I can write terrible code in Haskell, too. Does that prove anything? No.