3 ms·
If I understand correctly, Backpack's design is primarily driven by compatibility considerations (“how do we build upon GHC's existing foundation?”), rather tha
by catnaroek 11y ago
If I understand correctly, Backpack's design is primarily driven by compatibility considerations (“how do we build upon GHC's existing foundation?”), rather than elegance. In particular, Backpack doesn't eliminate those ugly .hs-boot files, it just automates and hides their generation and processing.
For all their faults, Standard ML and OCaml have pretty good support for modular programming. And, as the Modular Type Classes paper you linked shows, type classes can be built elegantly on top of a good modular foundation.
- Ericson2314 11y agoI agree that backpack leaves Haskell with too many overlapping concepts. But consider things could be unified internally, and compatibility-breaking language extensions introduced down the road. That's my hope at least :). Also, check out https://www.mpi-sws.org/~rossberg/1ml/ https://www.mpi-sws.org/~rossberg/1ml/ . I think it makes a pretty good argument that there is a similar problem going on with the MLs versus the ideal too. (The overlapping features are also not a subset of Haskell's overlapping features, interestingly too.)
- catnaroek 11y agoAs far as I can tell, Standard ML doesn't have much of a feature overlap problem. Off the top of my head, the only redundant feature is `abstype`, which I think is a leftover from the 70's, when ML didn't have its module system. If Standard ML had first-class modules, then modules and records could also be considered redundant. What Standard ML suffers from is lack of expressivity. The lack of (pattern) guards sometimes forces pattern matching blocks to (nest more than necessary and) contain redundant clauses. The lack of polymophic recursion forces non-uniformly recursive data types (as well as the functions that operate on them) to be rewritten in a way that makes the type checker a less effective bug-finding tool. Without higher-rank types, you can't express the Day convolution, free Applicatives, or Traversals (from the lens library). On the other hand, I don't find myself missing higher-kinded types much, since they are mostly useful in combination with type classes, which modules can adequately replace. What 1ML does is unify features: (0) records and let expressions are now particular uses of modules, (1) core language functions and type constructors are now particular uses of functors.
- Ericson2314 11y ago> On the other hand, I don't find myself missing higher-kinded types much... I don't find myself missing modules that much for precisely the inverse reason. > If Standard ML had first-class modules, then modules and records could also be considered redundant. If Haskell+Backpack had first class packages/modules, then packages/modules and type classes could also be considered redundant. This is the duality I am trying to get it :). Looking each language alone, the features are "somewhat orthogonal". But in the context of the entire design space, the lack of unification comes off as redundancy.
- catnaroek 11y ago> I don't find myself missing modules that much for precisely the inverse reason. The “tiny” detail is that ML modules do much more than what type classes do: they allow you to define abstract types whose representation is invisible to the rest of the program, without ugly hacks like `newtype`-wrapping the internal representation. > If Haskell+Backpack had first class packages/modules Packages and modules are completely different things. A package is a unit of distribution, whereas a module is a unit of encapsulation. Even within a single program that's only distributed as a whole, you may want different components to hide their internals from each other. > This is the duality I am trying to get it There is no duality between modules and type classes, because, while modules can do everything type classes do (and more), the converse does not hold.
- Ericson2314 11y agoRemember, it's the combination of type classes and higher kinded types that the MLs are up against. [Not because there is an inherent trade-off (because there isn't one between type classes vs modules either as the Dryer paper shows), but beause the MLs have that weakness.]
- catnaroek 11y agoNon-recursive higher-kinded types can be implemented in terms of functors. For example, the free monad type constructor is very easy to implement in Standard ML (OCaml is similar): signature FUNCTOR = sig type 'a t val map : ('a -> 'b) -> 'a t -> 'b t end functor FreeMonad (F : FUNCTOR) = struct datatype 'a t = Pure of 'a | Free of 'a t F.t (* operations go here *) end Modules can do everything type classes can do, and more. There is no weakness. The real reason why you need to define this as a higher-kinded type constructor in Haskell (`data Free f a = ...`) is to overcome the limitation of not having parameterized modules. The way it's done in Haskell also has the defect that the type system will happily allow you to construct a value of type `Free Foo a`, where `Foo` is not a functor, whereas the ML version prohibits this by construction.