[GHC] #13399: Location of `forall` matters with higher-rank kind polymorphism
GHC
ghc-devs at haskell.org
Fri Mar 10 02:30:31 UTC 2017
#13399: Location of `forall` matters with higher-rank kind polymorphism
-------------------------------------+-------------------------------------
Reporter: crockeea | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.2
Resolution: | Keywords: TypeInType
Operating System: Unknown/Multiple | Architecture:
Type of failure: GHC rejects | Unknown/Multiple
valid program | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by goldfire):
This is all expected behavior, for a sufficiently nuanced expectation.
This behavior may be undocumented however, which would be a bug.
The problem all boils down to this: '''there are no type-level lambdas.'''
When GHC transforms the term-level `f :: forall a. Int -> a -> a` to have
type `Int -> forall a. a -> a`, it does this by generating the Core `\(n
:: Int) @(a :: *) -> f a n`, which indeed works with `f` of the given type
and is an expression of the desired type. Note that there is a lambda
there. This is impossible at the type level. Thus: type-level `forall`s
don't "float".
The output from `:i` in comment:5 is an unrelated (but quite legitimate)
bug.
The `Foo`/`Goo` example comes from a nice rule around higher-rank
types/kinds: '''GHC never infers a higher-rank type''' (or kind). So, the
first (non-higher-rank) example with `Foo`/`Goo` succeeds. The second
fails, because GHC won't infer a higher-rank kind for `Goo`. If you make a
complete user-specified kind signature by putting a top-level kind
signature on the right-hand side of the `Goo` declaration, GHC will
accept, as it no longer needs to infer a higher-rank kind.
At the term level, GHC makes an exception to the never-infer-higher-rank
rule: when a term-level definition is by only one equation, and there is
no type signature, GHC computes the (potentially higher-rank) type of the
RHS and uses it as the type of the LHS. So, it's really the term level
that's behaving strangely by accepting `goo2`, not the type level. Looking
at this all, it seems sensible to propagate this exception to `type`
declarations, which are required to obey the one-equation rule used at the
term level.
Admittedly, the lack of "floating" makes higher-rank kinds unwieldy. I do
have a second use-case though:
{{{
data (a :: k1) :~~: (b :: k2) where
HRefl :: a :~~: a
class HTestEquality (t :: forall k. k -> Type) where
hTestEquality :: t a -> t b -> Maybe (a :~~: b)
data TypeRep (a :: k) where -- or, this could be the new proper
Data.Reflection.TypeRep
TInt :: TypeRep Int
TMaybe :: TypeRep Maybe
TApp :: TypeRep a -> TypeRep b -> TypeRep (a b)
instance HTestEquality TypeRep where
hTestEquality TInt TInt = Just HRefl
hTestEquality TMaybe TMaybe = Just HRefl
hTestEquality (TApp a1 b1) (TApp a2 b2) = do
HRefl <- hTestEquality a1 a2
HRefl <- hTestEquality b1 b2
return HRefl
hTestEquality _ _ = Nothing
}}}
The need for this came up while experimenting with (prototypes of) the new
`TypeRep`. See also [https://github.com/goldfirere/dependent-
db/blob/master/Basics.hs#L134 this related example], necessary to power
the dependently typed database example I used in my job talk.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13399#comment:6>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list