[GHC] #9840: Permit empty closed type families
GHC
ghc-devs at haskell.org
Fri Apr 17 20:17:04 UTC 2015
#9840: Permit empty closed type families
-------------------------------------+-------------------------------------
Reporter: adamgundry | Owner:
Type: feature request | Status: patch
Priority: normal | Milestone:
Component: Compiler (Type | Version: 7.8.3
checker) | Keywords:
Resolution: | Architecture:
Operating System: Unknown/Multiple | Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: #8028 | Differential Revisions: Phab:D841
-------------------------------------+-------------------------------------
Comment (by goldfire):
Replying to [comment:5 adamgundry]:
> > What Adam really wants here is the ability to create new type-level
constants at arbitrary kind.
>
> Is it?
Yes. :) But you don't know it yet.
After posting this morning, I thought more about this. The more I thought
about it, the more I liked it.
The key idea (for me) is that currently Haskell has many different forms
of type-level symbol declaration (`data`, `newtype`, `type family`, `data
family`, `type`, `class`, maybe more?), but perhaps these can all be
rolled into one, more flexible type of declaration. (I'm not necessarily
proposing to expose this to users as such, but to think of it this way.)
At the moment, I'm concerned only with how these type-level symbol
declarations behave in types, completely forgetting about any term-level
behavior. I'm also forgetting about FC for the moment, concentrating only
on Haskell.
* `data`: Declares generative, injective constants whose result kind must
be `*`. Can be pattern-matched. When considered as a kind, the set of
inhabitants is closed and always known.
* `newtype`: Identical to `data`, except that `newtype`s are neither
generative nor injective under representational equality.
* `type family`: Not generative, not injective. Accordingly, must appear
always saturated. (GHC's type variable application operation in types --
that is, `a b` where `a` and `b` are type variables -- assumes that the
function is generative & injective. Anything that isn't must always be
saturated.) These have a limited reduction behavior known to GHC. Closed
type families have a fixed reduction behavior; open type families'
reduction behavior can be extended. Cannot be pattern-matched against.
* `data family`: Generative & injective. When considered as a kind (in the
future with kind equalities) the set of inhabitants is open, but each
extension of this set requires parameters to be apart from previous sets.
Can be pattern-matched against.
* `type`: Like a `type family`, but with even more limited behavior.
* `class`: Like `data`, but the result kind must be `Constraint`.
Phab:D202 extends this collection with injective type families, which are
like type families, but allow injectivity in some subset of its
parameters.
I have wanted the following:
* A generative, injective type constant, whose result kind is `*`. When
considered as a kind, the set of inhabitants is open. Can be pattern-
matched against.
This is like `*`, but still distinguished from `*`. One may argue that
this is like `Symbol`, but I want to be able to hook into GHC's module
system to disambiguate identically-named inhabitants. I wanted this for
`units`, where I settle for declaring my extensible set of units in kind
`*`. This leads to worse error messages than would be possible if I could
declare a new, open kind.
* A generative, injective type constant that can '''not''' be pattern-
matched against.
This is the right place for `Any`.
Adam seems to want:
* A non-generative, non-injective type-level symbol with reduction
behavior unknown to GHC. This cannot be pattern-matched against.
The reduction behavior is implemented in a plugin. This type of
declaration is also the correct characterization of the type-lits
operators.
So it seems that there are several characteristics each type-level
declaration varies in:
* Generativity (possibly different choices for nominal vs.
representational equality)
* Injectivity (possibly different choice for nominal vs. representational
equality, and per argument)
* Matchability (if something is matchable, it had better be generative and
injective, too!)
* Open/closed
In addition, GHC blesses type families (and type synonyms) with a limited
form of reduction.
-------------------
I'm not totally sure where all of this goes, but somehow classifying this
menagerie seems meaningful. It also helps to identify missing spots and to
understand what is going on better. Perhaps using empty closed type
families for Adam's needs and for type-lits is OK, but it isn't really
what we want, according to these classifications: these type-level symbols
have an unknown reduction behavior, in contrast to empty closed type
families, which have a known (vacuous) reduction behavior.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9840#comment:6>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list