[GHC] #10281: Type error with Rank-n-types
GHC
ghc-devs at haskell.org
Fri Apr 17 12:21:37 UTC 2015
#10281: Type error with Rank-n-types
-------------------------------------+-------------------------------------
Reporter: rhjl | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler (Type | Version: 7.10.1
checker) | Keywords:
Resolution: | Architecture:
Operating System: Unknown/Multiple | Unknown/Multiple
Type of failure: GHC rejects | Test Case:
valid program | Peirce_eq_LEM.hs
Blocked By: | Blocking:
Related Tickets: | Differential Revisions:
-------------------------------------+-------------------------------------
Comment (by rhjl):
Replying to [comment:7 simonpj]:
> Could you propose some actual, concrete sentences to add or change in
user manual? Then I'll just make the change. As a bona fide user you are
in a far better position to draft the words than me.
In 7.13.6 [Arbitrary-rank polymorphism], before two paragraphs “The
`-XRankNTypes` option is also […]” and “The obselete [sic] language
options […]” add:
In particular, in `data` and `newtype` declarations the constructor
arguments may be polymorphic types of any rank. Note that the declared
types are nevertheless always monomorphic. This is important because by
default GHC will not instantiate type variables to a polymorphic type (cf.
7.13.7 [Impredicative Polymorphism]). The examples below demonstrate some
uses.
In 7.13.6.1 [Examples] replace the first two sentences with
These are examples of `data` and `newtype` declarations with polymorphic
constructor arguments:
After the code that shows the types of the constructors add the following:
By default GHC will not instantiate type variables to a polymorphic
type: given
{{{#!hs
f :: (forall a. a -> a) -> (forall a. a -> a)
}}}
the term `f id` has type `forall a. a -> a`, but the term `id f` cannot
be assigned a type because that would require an instantiation of `forall
a. a -> a` with the polymorphic type of `f` in place of the type variable
`a`. This does not present a problem when typing the term `id id`; the
typing in that case proceeds as follows:
1. the top-level quantifiers in the types of the two occurrences of `id`
are removed, and their bound variables are renamed to make them unique.
This gives types `a -> a` and `b -> b`;
2. the type variable `a` is instantiated to the – now monomorphic – type
`b -> b`;
3. the free variable `b` in the result-type `b -> b` of the function
application is universally quantified;
The same procedure for `id f` gives `f` the type `(forall a. a -> a) ->
b -> b` for some unique type variable `b` in step 1, by removing the
effectively top level quantifier to the right of the arrow. The resulting
type is nevertheless still polymorphic, and so step 2 fails. [I hope that
I got this whole explanation remotely correct. Please feel free to
improve it: I am sure that it can be expressed both briefer and more
accurately. What I say here also does not explain why the definition `f =
id` works, and in fact I am somewhat confused by that.] The next example
illustrates how one can use `newtype` declarations to work around this
issue.
{{{#!hs
type Poly = (forall a. a -> a) -> (forall a. a -> a)
newtype Wrap = Wrap { unwrap :: Poly }
f :: Poly
f = id
ok :: Poly
ok = unwrap (id (Wrap f))
}}}
In 7.13.7 [Impredicative Polymorphism] replace the sentence “This means
that you can call a polymorphic […]” with
Impredicative polymorphism allows type variables to be instantiated to
polymorphic types (cf. 7.13.6 [Arbitrary-rank polymorphism]). For example
the following is valid with `-XImpredicativeTypes`:
{{{#!hs
type Poly = (forall a. a -> a) -> (forall a. a -> a)
f :: Poly
f = id
ok :: Poly
ok = id f
}}}
In this example the type variable `a` in the type `forall a. a -> a` of
`id` needs to be instantiated to a polymorphic type. Contrast this with
the discussion in 7.13.6.1 [Examples] for more details.
In particular impredicative polymorphism also allows the application of
type constructors to polymorphic types, and of various term constructors
to terms of polymorphic types. For example, given the above definitions,
the following makes sense:
{{{#!hs
ok2 :: [Poly]
ok2 = [f]
}}}
Here is a more elaborate example: [continue with the current example]
> > By the way: this issue with impredicative instantiations precludes the
use of `($)` and `(.)` to get rid of excessive parenthesis in certain
situations. Is there a workaround?
>
> Becuase of this `($)` has its own special typing rule in GHC. But `(.)`
does not (yet).
Is the special type of `($)` only available when using the Prelude?
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10281#comment:8>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list