Alternative implementations of Haskell's standard library type classes

北城以北 提交于 2019-12-30 05:48:06

问题


I've seen many people complaining about some of the type classes from the standard library saying things like "Monad should require Functor" or even "Monad should require Applicative", "Applicative should require Pointed", "Num shouldn't require Show", etc, So, I have some questions:

  1. Are there arguments for the way the tree of type class dependencies have those "flaws" perceived by the community or is this just the result of how things were done historically?

  2. How drastically a change in this would break existing code?

  3. Are there alternative implementations of the basic type classes (particularly arrows, monads, applicative, etc...) around that implement the "right" set of class dependencies?


回答1:


Beyond backwards compatibility, there are some (mostly cosmetic, but tedious to deal with) issues due to the fairly simple way that Haskell treats type classes:

No upward implicit definition: Monad is fully defined by just pure and (>>=); fmap and (<*>) can be written in terms of those. In a "proper" hierarchy, each instance would need to be written out. It's not too bad in this case but as the granularity increases so do the number of instances that each add some small function. It would simplify things substantially if class definitions could supply default implementations for superclass functions in terms of their own functions, so that functions like (>>=) which fully subsume multiple functions in superclasses can serve as a definition for the entire relevant hierarchy.

Context bloat: Insofar as there's a "reason" that Num requires Show and Eq, it's because printing and comparing equality of numbers is pretty common. These are strictly orthogonal, but separating them means that functions doing all three things now have to specify all three classes in their type. This is technically a good thing but, again, as granularity increases so will function type signatures.

Monolithic dependencies: A hierarchy of type classes and their superclasses can be added to, but not altered or replaced. If a piece of code feels the need to substitute its own version of some common type class--say, using something like this to replace Monad--the hierarchy is cut off at that point; compatibility with code using other definitions of Monad must be provided manually to some degree, and any type classes built on top of the other definition have to be reimplemented or translated even when reliant on only a subset of behavior that both definitions share.

No clearly correct hierarchy: As implied by the above, there are choices to be made in the granularity of the classes. For instance, does Pointed really need to exist, or does just Applicative suffice? There's really no answer here that's universally ideal, and there shouldn't have to be.

I suspect that efforts to replace the existing type classes would be better served by first tackling the above issues, after which replacing the type classes would be far less painful, or even little more than a formality. The type class synonyms proposal that @luqui mentions, for instance, would be a major step in this direction.




回答2:


There's been a recentish discussion about this on the Haskell-prime list, I think what transpired from there is that for a hierarchy change to happen, a proposal of Jón Fairbairn would need to be implemented first, which fixes the very, very important point 1 of @camccan's list: A typeclass could give default implementations for its superclass definitions. I don't know of any implementation, or even half-way formal specification of that proposal.

Type class synonyms fix point #2, Context bloat. Note that you can already do that, provided you're fine with using UndecidableInstances (and having GHC expand the synonym each time it infers a type...)

As to #4, having decent fixes for #1 and #2 fixes most of the practical issues. Things get more hairy if it's not a mere question of granularity (the answer there is synonyms, including writing instances for whole type class synonyms), but having a choice of multiple possible superclasses, I think this comes up when it comes to a mathematical Num-hierarchy. A solution to that (alternative subclasses?) has a fair chance of solving #3 along the way.

In any case, though, I think the effort is worth the bother, as having those changes made to Haskell (not only to the hierarchy) would definitely make both Haskell and Haskell code more flexible and thus pull the rug out under the nay-sayer's current arguments.




回答3:


  1. I oppose vicarious existence and also I cannot take the credit for the proposal which is related to Applicative-Functor-Monad hierarchies. I had made mutterings years ago on the need for a mathematically sound Prelude.

  2. One obstacle to a typeclass hierarchy is present at the very beginning with monoids. For example, integers form both an additive and a multiplicative monoid. Coq solves this through multiple inheritance.

    One great advantage of having a mathematical hierarchy with a constructive mathematics proof system is that we can extract programs from proofs through the Curry-Howard isomorphism. For those interested in program correctness and automated verification, having direct translations between Haskell typeclasses and proof-verification tools like Coq is nifty.

    I currently use the hmatrix package and friends. Unfortunately, I don't think it plays well with the current Numeric Prelude on hackage. Ideally, to use the optimised BLAS and LAPACK libraries in generic code, one should just have to implement a typeclass interface specified in the Numeric Prelude.




回答4:


  1. Some unidentified person or persons (acting through Vivian McPhail) have proposed a reform of this area of the prelude, and open their proposal by stating "The standard class hierarchy is a consequence of Haskell's historical development, rather than logic". Whether this is true or not, i cannot say.

  2. The proposal above includes measures to support backwards compatibility, but it seems like it wouldn't be perfect by any means.

  3. There was a brief but glorious attempt to create The Other Prelude to tidy up some of the mess.



来源:https://stackoverflow.com/questions/5730270/alternative-implementations-of-haskells-standard-library-type-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!