[GHC] #11471: Kind polymorphism and unboxed types: bad things are happening
GHC
ghc-devs at haskell.org
Mon Feb 8 17:01:17 UTC 2016
#11471: Kind polymorphism and unboxed types: bad things are happening
-------------------------------------+-------------------------------------
Reporter: bgamari | Owner: goldfire
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler (Type | Version: 7.10.3
checker) | Keywords: TypeInType,
Resolution: | LevityPolymorphism
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by rwbarton):
So under comment:7 as I understand it `*` is a synonym for `TYPE L`. We
can make a table
{{{
1 :: Int and Int :: * = TYPE L
2# :: Int# and Int# :: TYPE UW64
3.0# :: Double# and Double# :: TYPE UF64
Int :: * and * :: * = TYPE L
}}}
The last line is given to us by TypeInType. But to me the thing `Int`
seems at least as different from the thing `1` as the things `1`, `2#` and
`3.0#` are from each other. So, the suggestion is to add another
constructor `T` to `RuntimeRep` and replace the last line with
{{{
Int :: * and * :: TYPE T
}}}
We could define a synonym `type Kind = TYPE T` and then `* :: Kind`.
The motivation is basically: By merging the type and kind levels,
TypeInType means that we no longer ''need'' to distinguish types and
kinds. That is great for implementing, say, kind coercions because we
don't need to duplicate the language of coercions to the kind level any
more. (Feel free to substitute your own, better examples.) However, now
that this RuntimeRep story has emerged, it seems we could get the best of
both worlds, by defining `* = TYPE L`, and `Kind = TYPE T`. Now we can
abstract over the difference between types and kinds when we want to, by
working with `TYPE t`. Or we can distinguish between types and kinds when
that makes sense, by using `*` and `Kind`.
I don't have any great examples for the latter. Maybe if you define a type
family whose result is intended to be a kind (since you use it to classify
a type elsewhere) you would want to be able to enforce that on clients who
may define their own instances. Or maybe the typing rule for a coercion
should be that the type `s ~ t` of coercions is well-formed only if `s ::
TYPE r` and `t :: TYPE r` for the same `r`, and you don't want to allow
coercing between values and types. (But see the end of this comment.)
----
Note that one could perhaps retain even more of the type/kind/sort/etc.
hierarchy by adding a parameter to `T`. The parameter `r` would contain
information about the representation of the "values" (types) classified by
types of kind `TYPE (T r)`. Or in symbols,
{{{
if C :: K = TYPE r, (i.e., the type C has representation r)
then K :: TYPE (T r),
}}}
or in short `TYPE r :: TYPE (T r)`. I'm not sure how this would interact
with type constructors though (with kinds built from `(->)`). This
probably has something to do with the indexed TypeRep story also, which I
haven't been paying any attention to.
----
These suggestions apply to an unspecified extension of Haskell that might
want to treat the type level in an arbitrary way. If there's a specific
plan for "GHC Haskell" to identify types with their TypeReps as mentioned
in comment:10 (I guess this means there is some way to refer to a type at
the value level, so now it really makes sense to write functions of type
`* -> *`, etc.) then there is probably not much reason to take this route,
indeed.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11471#comment:13>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list