{-# OPTIONS_GHC -fglasgow-exts #-}

class Foo a b | a -> b where
  foo :: Foo b c => a -> Maybe c

instance Foo String () where foo _ = Nothing
instance Foo Int String where foo 4 = Just (); foo _ = Nothing


There appears to be a type-safe way to use unsafeCoerce# for this:

--------
import qualified GHC.Exts

class Foo a b | a -> b where foo :: a -> FooBox b
data FooBox b = forall c. Foo b c => FooBox (Maybe c)

instance Foo () ()
instance Foo String () where foo _ = FooBox Nothing
instance Foo Int String where foo 4 = FooBox $ Just (); foo _ = FooBox Nothing

runFoo :: (Foo a b, Foo b c) => a -> Maybe c
runFoo x = case foo x of FooBox x -> GHC.Exts.unsafeCoerce# x
--------

The class constraint check of a,b,c gets moved to the runFoo method instead of the instance declarations. Between the body of foo and the call to foo in runFoo, type 'c' is unknown to the compiler, so we have to encapsulate it in a FooBox. The unsafeCoerce# is safe because the type constraint (Foo b c) that we've placed both on FooBox and on runFoo permits c to have only the type uniquely specified by b.

We actually could remove the Foo constraint on FooBox, which makes the code no longer typesafe but it will still work just fine.

_________________________________________________________________
Don’t miss your chance to WIN 10 hours of private jet travel from Microsoft® Office Live http://clk.atdmt.com/MRT/go/mcrssaub0540002499mrt/direct/01/

_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to