
All, I'm after advice on whether the following example is a safe use of unsafeCoerce, and if it is safe, if it's worth it. In summary, if the following is ok: castFooToBar :: Ptr Foo -> Ptr Bar castFooToBar = castPtr then is the following ok? newtype Foo' = Foo' (Ptr Foo) newtype Bar' = Bar' (Ptr Bar) castFooToBar' :: Foo' -> Bar' castFooToBar' = unsafeCoerce Here's the context/motivation: In the gtk2hs bindings for Haskell we model Gtk's object hierarchy by a hierarchy of Haskell classes and corresponding instances (and newtypes of ForeignPtrs). Here's the pattern: --The base class: newtype GObject = GObject (ForeignPtr GObject) mkGObject = GObject unGObject (GObject o) = o class GObjectClass o where toGObject :: o -> GObject fromGObject :: GObject -> o instance GObjectClass GObject where toGObject = id fromGObject = id --A derived class newtype Widget = Widget (ForeignPtr Widget) mkWidget = Widget unWidget (Widget o) = o class GObjectClass o => WidgetClass o toWidget :: WidgetClass o => o -> Widget toWidget = fromGObject . toGObject fromWidget :: WidgetClass o => Widget -> o fromWidget = fromGObject . toGObject instance WidgetClass Widget instance GObjectClass Widget where toGObject = mkGObject.castForeignPtr.unWidget fromGObject = mkWidget.castForeignPtr.unGObject So you can see in the instance of Widget for the GObjectClass we're basically doing a pointer cast (and wrapping & unwrapping newtypes). In C they just cast pointers. I'm wondering if we can do the same, ie define the instance like so: instance GObjectClass Widget where toGObject = unsafeCoerce fromGObject = unsafeCoerce Of course there's not much point, but if we know that toGObject & fromGObject are just doing a cast, then we can get rid of the class methods on GObjectClass and just implement them as ordinary class constrained functions: toGObject :: GObjectClass o => o -> GObject toGObject = unsafeCoerce fromGObject :: GObjectClass o => GObject -> o fromGObject = unsafeCoerce So, the point is we can remove entirely the class dictionary that otherwise has to be carried round for every object and the upcasting & downcasting functions no longer need to do slow dictionary lookups when all they are really doing is casting C pointers. So is it a) safe? b) kosher? BTW I know fromGObject is doing an unchecked downcast, it is only used internally, we have safe checked ones that we expose in the interface. Duncan

I'm after advice on whether the following example is a safe use of unsafeCoerce, and if it is safe, if it's worth it.
It looks like it is safe but it feels like using a sledgehammer to crack a nut ... in the presence of small children/ curious animals/ two left thumbs/ etc. so you have to take great care that none of them are near the nut each time you pull that sledgehammer out. Given the function castFooToBar (which you tell us is safe), there's a number of obvious typesafe ways of writing this code, why not do so? [I accept that there could be some reasons I just didn't see you mention any.] -- Alastair Reid

On Mon, 2004-04-26 at 15:42, Alastair Reid wrote:
I'm after advice on whether the following example is a safe use of unsafeCoerce, and if it is safe, if it's worth it.
It looks like it is safe but it feels like using a sledgehammer to crack a nut ... in the presence of small children/ curious animals/ two left thumbs/ etc. so you have to take great care that none of them are near the nut each time you pull that sledgehammer out.
Given the function castFooToBar (which you tell us is safe), there's a number of obvious typesafe ways of writing this code, why not do so? [I accept that there could be some reasons I just didn't see you mention any.]
In the context of the Gtk class hierarchy, we do currently have a type safe way of doing it (wrapBar.castForiegnPtr.unwrapFoo), but I'm trying to eliminate the class dictionary overhead. I'm open to other suggestions. Duncan
participants (2)
-
Alastair Reid
-
Duncan Coutts