[GHC] #7015: Add support for 'static'
GHC
ghc-devs at haskell.org
Wed Aug 20 21:40:09 UTC 2014
#7015: Add support for 'static'
-------------------------------------+-------------------------------------
Reporter: edsko | Owner:
Type: feature | Status: patch
request | Milestone: 7.10.1
Priority: normal | Version: 7.4.2
Component: Compiler | Keywords:
Resolution: | Architecture: Unknown/Multiple
Operating System: | Difficulty: Unknown
Unknown/Multiple | Blocked By:
Type of failure: | Related Tickets:
None/Unknown |
Test Case: |
Blocking: |
Differential Revisions: Phab:D119 |
-------------------------------------+-------------------------------------
Comment (by mboes):
> * It would be tremendously helpful to partition the wiki page into
three layers:[[BR]][[BR]]
Thank you for this suggestion regarding structure. We will update the wiki
page shortly.
> * I see the need for `Ref` vs `Static`; the latter allows comosition;
the former is just a code pointer. But I don't understand what
`GlobalName` is doing, nor why `Static` needs two type parameters. All
very mysterious.
This should become clearer once we expand the scope of the wiki page. A
quick primer: `GlobalName` is to `Ref` what `Addr#` is to `Ptr`. That is,
just like `Ptr` is a wrapper around `Addr#` adding a phantom type
parameter, so is `Ref` a wrapper around `GlobalName` adding a phantom type
parameter.
In our current scheme, `Static` is not a datatype defined in base. Only
`Ref` is. `Static` is provided by an add-on package which already exists
and that we are largely reusing: `distributed-static`. The only thing we
have changed here is to make `distributed-static` parametric in the label
type. Wherease `distributed-static` used to only support user strings as
the label type, it is now parametric so that those users that are using
Cloud Haskell on a current compiler (not supporting the `static` keyword
extension), can still use the `distributed-static` package. That's where
the `l` parameter in `Static l a` comes from: `l` is the label type. When
using `static`, the label type is a `GlobalName`. When not using it, one
typically uses a free form string. Or some custom datatype with one
constructor per possible remotable function, if one prefers to in effect
manually defunctionalize.
> The major open issue, but one that it not treated head-on in the wiki
page, is that of '''polymorphism'''. Polymorphism simply isn't discussed
by the Cloud Haskell paper.
> [...]
> So unless we do something we'll probably end up with `y2`, and that is
problematic because if we write it out in System F we'll see
> {{{
> y2 :: forall a. Static ([a] -> [a])
> y2 = /\a. static (reverse a)
> }}}
> so the argument to `static` hsa a free variable, namely `a`, that is not
bound at top level. I ''believe'' (see #9429), that some CH users are
somehow doing this: instantiate the polymorphic function at `Any`, and
send that:
> {{{
> y2 :: Static ([Any] -> [Any])
> y2 = static (reverse Any)
> }}}
> Now at the other end, you use `unstatic` to get `[Any] -> [Any]`, and in
some way I do not understand, convert it to `forall a. [a] -> [a])`.
Yes, in this respect, we haven't changed anything to how `distributed-
process` is already doing things today. Currently, `distributed-process`
already uses the `Any` "hack" for a number of internal remotable
functions. In fact Well-Typed developed an entire package to support this,
called `rank1dynamic`. It has an implementation of first-order
unification, so that on the remote end where say `[Any] -> [Any]` is
expected, it is perfectly fine to send a function of type `[Int] ->
[Int]`, because `isInstanceOf (typeOf x) (typeOf y) == True` if `x ::
[Int] -> [Int]` and `y :: [Any] -> [Any]`.
So while there was an effort to not upheave the status quo too much,
that's not to say that we shouldn't.
The crux of the issue is: a) no first class representations of polymorphic
types, b) avoiding impredicative types, because the support for that in
GHC is patchy at the moment AFAIU.
> But all this `y2` stuf is clearly a Gross Hack, and one that becomes
even clearer when we have overloaded functions like `sum :: forall a. Num
a => [a] -> a`. Now the `y2` equivalent really isn't going to work. With
explicit System F notation:
> {{{
> z2 :: forall a. Num a => Static ([a] -> a)
> z2 = /\a \(d:Num a). static (sum a d)
> }}}
> Now the `(sum a d)` has a free ''value'' variable `d`, which is lambda
bound, so now `static` really cannot work. Again what we really want is
> {{{
> z1 :: Static (forall a. Num a => [a] -> a)
> z1 = static sum
> }}}
> I'll stop here for now.
Yes. FWIW, in the current implementation, we don't allow unresolved
constraints in the type of the body of a static form. We have discussed
this issue at length, both internally and with Edsko and Duncan. At this
point, we simply don't know how to deal with constraints well, though
Edsko did share with us some ideas that from an earlier discussion with
you. I'll try to dig out that email from somewhere.
It's worth noting that all overloaded functions can be handled with some
help from the user, as discussed on the wiki page (conceivably the
compiler could do this automatically):
{{{
data Dict c = c => Dict
showD :: Dict (Show a) -> String
showD Dict = show
t1 = static showD -- this works.
}}}
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/7015#comment:21>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list