4 ms·
Counterexamples of Type Classes
- lmm 11y agoOne example I found of an Applicative which is not a Monad is Const[K: Monoid] - <*> is just monadic plus, but you can't flatMap because there's no way to "get a value out" of it. This is a good reason to implement traverse in terms of Applicative rather than Monad - foldMap then becomes just a special case of traverse.
- hesselink 11y agoThis stack overflow question has some more nice examples: http://stackoverflow.com/questions/7220436/good-examples-of-not-a-functor-functor-applicative-monad http://stackoverflow.com/questions/7220436/good-examples-of-...
- chriswarbo 11y agoOne effect of such counterexamples is that they lead to the kind of single-method type classes shown in the article; at which point, a type class is essentially a shorthand synonym for that method's signature. This kind of proliferation fits interestingly into the arguments given in http://www.haskellforall.com/2012/05/scrap-your-type-classes.html http://www.haskellforall.com/2012/05/scrap-your-type-classes... Of course, type classes still offer a couple of extra niceties, e.g. that type class instances can be inferred whilst extra arguments generally can't, and that instances are globally consistent (this is important for `Set`, which the article also mentions is a counterexample to `Functor`). Still, type classes seem to appear less and less elegant as time goes on (e.g. compare their use in dependently typed languages). I'm optimistic though, as that indicates that we're asking questions and setting expectations of our systems above and beyond what was common 20 years ago.
- lmm 11y agoA typeclass should indicate some semantic relationship between its instances, so IMO they do provide a safe version of ad-hoc polymorphism. You shouldn't have to name the (type, operation) pair; the whole point of typeclass coherence is that specifying the type and the operation is enough. I do think typeclass programming could do with having the same functionality as ordinary programming available. Here in Scala typeclasses are ordinary values (resolved via an implicit mechanism), which enables a lot - though the cost of abandoning global coherence is high. Ultimately, syntax and conciseness does matter. I don't think anything as verbose as that link has a chance of getting off the ground.
- whateveracct 11y agoI wouldn't call the "cost of abandoning global coherence" to be "high." Outside of data structures that depend on typeclass instances (like Set), it doesn't especially harm my ability to reason about my or others' code in my experience. And the data structures issue (what happens when I join two Sets with potentially different Order instances) can be solved with Scala's dependent type features I believe.
- lmm 11y ago> And the data structures issue (what happens when I join two Sets with potentially different Order instances) can be solved with Scala's dependent type features I believe. Not really. There's no way to enforce that each Order has a singleton type which is what you'd need to resolve that.
- purescript 11y ago> Still, type classes seem to appear less and less elegant as time goes on I think part of the problem is that type classes are so easy to abuse. When you have a problem like e.g. monad transformers, where a) you have a lot of boilerplate code which would be irksome if written out by hand, b) you have laws to make sure the generated code is sensible, and c) your types have exactly one such sensible instance, then classes are very nice. Abuses of type classes exist where any of the three above conditions fail to hold IMO, and a scrap-your-typeclasses approach can be very valuable then.
- andrewflnr 11y agoI think that guy independently re-invented ML-style module-based dispatch.