Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> 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?



> 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 -- This abomination would not have happened in Haskell.


>> 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. :-)


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


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


> That's just non-sense. In Scala typeclass instances are just part of the equation. That's just not a big deal at all.

The important part of the equation that Scala misses is that, when a value V has a type T that is an instance of a type class C, then V has to respect the laws associated to C. Granted, this is not enforced statically (because it requires dependent types), but instance uniqueness allows you to confine all the manual testing/enforcement to the point where the instance is defined.

> LOL. I guess that's a joke, right?

No OverlappingInstances, no UndecidableInstances, no ImpredicativeTypes, no DataKinds, no PolyKinds... sounds fairly conservative to me.

> There is no incorrectness. The code you have written does exactly what you have specified.

Dereferencing a dangling pointer is undefined behavior, and in particular, it may cause a segfault. Just as specified.

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

This kind of argument I expect from dynamic language folks, not from Scala proponents.


> when a value V has a type T that is an instance of a type class C, then V has to respect the laws associated to C

And that's exactly what happens in Scala if you cared to look at actual code.

The only difference is that one can associate different values with different typeclass instances.

If you decide not to associate values with specific typeclass instances and instead write code which accepts arbitrary instances, despite the fact that the values invisibly depend on a specific one ... sorry, that's just plain dumb.

That's like writing an API which accepts numbers and an arbitrary operation on those numbers, but only returns reasonable results for addition; and then complain that your code is fine as long as the "arbitrary operation" is addition.

No compiler on this planet can fix a lack of brain cells.

> Dereferencing a dangling pointer is undefined behavior, and in particular, it may cause a segfault. Just as specified.

If you can't see the difference yourself, I can't help you.

> This kind of argument I expect from dynamic language folks, not from Scala proponents.

Yeah, sorry. Haskell users know how to deal with different programming languages, but the latest influx of HN's "I-read-something-about-Haskell-on-the-internet-a-few-minutes-ago-let's-tell-everyone-how-dumb-they-are-to-show-my-new-intellectual-superiority-as-a-Haskell-expert"-kids has muddied the water a bit and caught me a bit off-guard, because I usually deal with thinking people only.


> And that's exactly what happens in Scala if you cared to look at actual code.

My example notwithstanding? Heh.

> If you decide not to associate values with specific typeclass instances and instead write code which accepts arbitrary instances, despite the fact that the values invisibly depend on a specific one ... sorry, that's just plain dumb.

I am not disagreeing that it is dumb. I am complaining that the language allows me to do something that is dumb in first place. This is attitude towards correctness (the language washing its hands of having to deal with it) is what I dislike.

> If you can't see the difference yourself, I can't help you.

There is no difference. In both cases, an undesirable behavior is possible because of a hole in the language's design.

> Yeah, sorry. Haskell users know how to deal with different programming languages

Yes, exactly. The way I deal with Scala is to not use it.


>> And that's exactly what happens in Scala if you cared to look at actual code.

> My example notwithstanding? Heh.

Yes. Just go and read some code instead of using your imagination. Compare for instance TreeSet.apply and List#sorted.

> I am complaining that the language allows me to do something that is dumb in first place. This is attitude towards correctness (the language washing its hands of having to deal with it) is what I dislike.

Then you should dislike Haskel, too, because that's exactly what Haskell allows you to do, too.

  Prelude> let getLargestElement (x:xs) = x
  Prelude> getLargestElement [3,2,1]
  3
  Prelude> getLargestElement [1,2,3]
  1 -- OMG!!!
Haskell is sooo incoherent! I wrote a function that obviously relies on that the input is sorted in a certain way, but Haskell let's me pass arbitrary lists to it! How dumb is that?! Haskell has a really terrible attitude towards correctness!

>> Yeah, sorry. Haskell users know how to deal with different programming languages

> Yes, exactly.

Sorry, but you've been sorted into the I-read-something-about-Haskell-on-the-internet-a-few-minutes-ago-let's-tell-everyone-how-dumb-they-are-to-show-my-new-intellectual-superiority-as-a-Haskell-expert category already, so this doesn't really apply to you.

> The way I deal with Scala is to not use it.

That's perfectly fine, but please stop commenting on things you don't understand. You are only embarrassing yourself.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: