[GHC] #13305: static: check for identifiers should only consider term level variables
GHC
ghc-devs at haskell.org
Wed Feb 22 13:48:11 UTC 2017
#13305: static: check for identifiers should only consider term level variables
-------------------------------------+-------------------------------------
Reporter: edsko | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.2
Resolution: | Keywords:
| StaticPointers
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 mboes):
I think this is simply a case of a bad error message. The error message
should say that what's missing here is the `Typeable` constraint on `a`.
The spec is pretty simple: parametric polymorphism is allowed, ad hoc
polymorphism is not. BUT, type variables each give rise to `Typeable`
constraints. So
{{{#!hs
:: StaticPtr (Int -> Int) -- is legal
:: StaticPtr (a -> a) -- is illegal
:: Num a => StaticPtr (a -> a) -- is illegal
:: Typeable a => StaticPtr (a -> a) -- is legal
:: Typeable a => Dict (Num a) -> StaticPtr (a -> a) -- is legal
}}}
This is because it doesn't make sense to point to something whose type I
can't describe. And I can only describe some type `T[a,b]` if I know that
`a` and `b` are `Typeable`.
In the future, one might imagine that when looking up a pointer to some
value `foo` in the SPT, we check that the concrete monotype at which we're
doing the lookup is legit wrt the (poly)type of `foo` recorded in the SPT.
The details of how this works haven't been fleshed out fully by anyone as
far as I'm aware, but we at least know that this ought to be possible to
do (for prenex polymorphic types) provided we have the `Typeable`
dictionaries for all the type variables.
Do we really need parametric polymorphism? Yes we do, I would argue. It is
used quite a bit in a project like sparkle. See for example
http://hackage.haskell.org/package/distributed-closure. The package
defines what a `Closure` is. It says that `Closure` is a `Functor`-like
thing, in that you can define
{{{#!hs
cmap :: ... => Closure (a -> b) -> Closure a -> Closure b
}}}
It is moreover a (quasi) `Applicative`-like thing, in that you can define
{{{#!hs
cpure :: ... => a -> Closure a
cap :: ... => Closure (a -> b) -> Closure a -> Closure b
}}}
But surely I must be cheating. What's in the `... =>` part of the
signature for `cpure`? We want something like `Serializable a =>`, because
I can only lift into a closure what I know how to (de)serialize. So far so
good?
Now let's look at the real definition of `cpure`:
{{{#!hs
data Dict c = c => Dict
decodeD :: Typeable a => Dict (Serializable a) -> ByteString -> a
decodeD Dict = decode
cpure :: Typeable a => Closure (Dict (Serializable a)) -> a -> Closure a
cpure cdict x | Dict <- unclosure cdict =
Closure x $
StaticPtr (static decodeD) `cap`
cdict `cap`
Encoded (encode x)
}}}
GHC doesn't currently allow me to have `Serializable a => ...` directly,
but I can work around that just fine using `ConstraintKinds` and the "dict
trick" (your name). Notice the `(static decodeD)`: I'm making a static
pointer at a polymorphic type to `decodeD`.
If I couldn't do that, then I wouldn't be able to define a combinator like
`cpure` once and for all. I would need one per concrete type.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13305#comment:6>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list