Standarize GHC.Prim.Any

Isaac Dupree ml at isaac.cedarswampstudios.org
Sat Sep 5 23:35:29 EDT 2009


Maciej Piechotka wrote:
> On Thu, 2009-08-20 at 19:59 +0200, Maciej Piechotka wrote:
>> Sorry for delay in responding.
>>
>>>> Any from GHC.Prim makes unsafeCoerce much useful and safe. Can it be
>>>> included in Unsafe.Coerce module?
>>>>
>>>> Pros:
>>>> - unsafeCoerce is much more useful with Any (it's a safe placeholder for
>>>> any value and therefore can be passed simply in/out FFI).
>>> Yes it's a safe placeholder, but so is an existential, I believe...
>>> data ContainsAny = forall a. ContainsAny a
>>> to put in the container:
>>> "ContainsAny x"
>>> to remove from the container:
>>> "case ... of ContainsAny x -> unsafeCoerce x"
>>> Albeit, there might be a slight performance penalty for the extra box, 
>>> which can't be removed in all haskell implementations.
>>>
>>> Also, what do you mean about "FFI"?  I don't think you can pass the 
>>> "Any" type to foreign functions through the FFI...
>>>
>>> Also, can/do all compilers that implement unsafeCoerce implement a safe Any?
>>> Hugs can do it with just "data Any = Ignored" I believe, not sure about 
>>> nhc, yhc or jhc...
>>>
>>> -Isaac
>> Well. May be I have one specific problem which seems to not be possible
>> to be implemented in portable way (I'm not sure if it is possible
>> outside ghc). Sorry for mentioning FFI without further explanation.
>>
>> The problem arise if one would like to implement GClosure from glib.
>> Once it was implemented in gtk2hs in C using RTS API. I also have my own
>> implementation in Haskell which is doing something (removed IO monad for
>> clarity):
>> applyValue :: Any -> Value -> Any
>> applyValue f v =
>> 	case funsamentalTypeOf v of
>> 		Type1 -> (unsafeCoerce f :: HaskellType1 -> Any) $ get v
>> 		...
>>
>> Such trick is (looks for me?) safe as a -> b -> ... -> d can be
>> represented by Any. However I cannot safely cast to function a -> Any.
>>
>> To/from FFI it is passed in Ptr (StablePtr Any).
>>
>> Regards
>> PS. I assume that it is not possible as it was done in importable was in
>> gtk2hs. 
> 
> With any known from the beginning number of parameters function and GADT
> one can write:
> 
> data Closure where
> 	Closure0 :: IO a
> 	Closure1 :: a -> IO b
> 	Closure2 :: a -> b -> IO c
> 	-- ...

That isn't GADT syntax... results of "Constructor :: ..." must be 
"Closure" in this case.  What are you trying to do here?  An alternative 
for "Ptr (StablePtr Any)"?  Is "Ptr (StablePtr Dynamic)" sufficient, 
where Dynamic from Data.Dynamic is represented in an 
implementation-specific way equivalent to
data Dynamic = forall a. Typeable a => DynamicConstr a
a.k.a.
data Dynamic where DynamicConstr :: Typeable a => a -> Dynamic
?
The main limitation would be if you want to include a type that's not in 
Typeable.  Is that common, to have types that aren't in Typeable?

It would be more annoying but you could add extra concrete-type 
constructors to a data, for every possibility, like
   DynamicConstr3 :: (Int, Bool) -> MyDynamic
if for some reason (Int, Bool) weren't in Typeable... Would be silly to 
do, however.  Just put things in Typeable?  Or, if you know it'll be 
type-correct, just use ContainsAny as above, with "Ptr (StablePtr 
ContainsAny)"?

It might not be absolutely the most optimized, but portable standard 
mechanisms were never the place for that kind of hacking.  And it'll be 
good enough.  Right?

-Isaac


More information about the Haskell-prime mailing list