How do I write an actual instance declaration for Typeable? For instance, say I wanted to write an instance for Char where each character had a different type, e.g.
instance Typeable Char where
typeOf 'a' = C
typeOf 'b' = C -> D
typeOf 'c' = D -> E
typeOf = String
Obviously this wouldn't be written like this because the output of typeOf is a TypeRep, but I can't figure out how to actually construct a TypeRep.
Is this even possible? It seems like everything that talks about Typeable assumes that you would use DeriveDataTypeable.
Well there are a few issues with doing this.
It's broken. typeOf
isn't supposed to be strict in it's argument so typeOf (undefined :: Char)
should work.
It's unsafe. Actually, if you manually create an instance of Typeable
you won't compile under Safe Haskell.
Keeping this in mind!
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Typeable
data C = C deriving (Typeable)
data D = D deriving (Typeable)
data E = E deriving (Typeable)
newtype Foo = Foo Char
instance Typeable Foo where
typeOf (Foo 'a') = typeOf (undefined :: C)
typeOf (Foo 'b') = typeOf (undefined :: C -> D)
typeOf (Foo 'c') = typeOf (undefined :: D -> E)
typeOf _ = typeOf (undefined :: String)
Now as an example of why this is terrible, consider
what :: Char -> C
what c = if isJust weird then fromJust weird else error "Sanity!"
where weird = fromDynamic . toDyn $ Foo c
Now
> what 'a'
C
> what 'b'
*** Exception: Sanity!
Depending on the representation of how Foo
this could do all sorts of fun things, like seg fault, spew nonsense answers, or make monkeys fly out of your ears.
Robert Harper gave a more dramatic example
{-# LANGUAGE DeriveDataTypeable #-}
import Control.Exception
import Data.Typeable
newtype Foo = Foo (() -> IO ())
{- set Foo’s TypeRep to be the same as ErrorCall’s -}
instance Typeable Foo where
typeOf _ = typeOf (undefined :: ErrorCall)
instance Show Foo where show _ = ""
instance Exception Foo
main = Control.Exception.catch (error "kaboom") (\ (Foo f) -> f ())
Which gives
<interactive>: internal error: stg_ap_v_ret
(GHC version 7.6.3 for x86_64_unknown_linux)
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
C-c C-c
Process haskell aborted (core dumped)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With