| > We're not doing abstract category theory; we're writing computer programs (well, I am). Have you ever run into a problem with type families in that capacity? I like being able to reason about my programs. For that to be a smooth process, the language has to be mathematically civilized. > Agreed, but there's a difference between type functions and type constructors. TFs are (a limited form of) type functions. By “type families”, I meant both data families and type families. Case-analyzing types is the problem, see below. > And using ML-style modules is easy at the term level, but cumbersome at the type level. Actually, ML-style modules are also more convenient at the type level too! If I want to make a type constructor parameterized by 15 type arguments, rather than a normal type constructor in the core language, I make a ML-style functor parameterized by a structure containing 15 abstract type members. > How so? I really don't understand your argument here, if you just take TFs to be a limited form of type function. “In programming language theory, parametricity is an abstract uniformity property enjoyed by parametrically polymorphic functions, which captures the intuition that all instances of a polymorphic function act the same way.” https://en.wikipedia.org/wiki/Parametricity |
You can do this in Haskell with DataKinds (you just pass around a type of the correct kind which contains all the parameters). Admittedly, it is quite clunky at the moment. I did this to pass around CPU configuration objects for hardware synthesis a la Clash, as CPU designs are often parametrized over quite a few Nats.
> parametricity is an abstract uniformity property enjoyed by parametrically polymorphic functions
Whenever one introduces a typeclass constraint to a function, one can only assume that the function exhibits uniform behavior up to the differences introduced by different instances of the typeclass. There is no particular reason to assume that (+) has the same behavior for Int and Word, except insofar as we have some traditional understanding of how addition should work and which laws it should respect. The same is true for type families. It is not a problem that they introduce non-uniform behavior; we can only ask that they respect some specified rules with respect to their argument and result types.
Case-analyzing types in type families is no worse than writing a typeclass instance for a concrete type. Would you say that the fact that "instance Ord Word" and "instance Ord Int" are non-isomorphic is a problem? After all, the types themselves are isomorphic!