I am using an existential type as a wrapper. At a point in my code where I know the enclosed type, I want to do something with it that is specific to the enclosed type. This
You have to convince the type checker as well that you have the type is Bug
.
You can do this by making Data.Typeable.Typeable
a super-class of Agent
and then use Data.Typeable.cast
to downcast from the existential type to the actual type.
But before doing this, consider doing it some other way. This is not very Haskellish, but rather in OO style.
{-# LANGUAGE ExistentialQuantification, DeriveDataTypeable #-}
import Data.Typeable
import Data.Maybe
class Typeable a => Agent a where
agentId :: a -> String
speciesId :: a -> String
data AgentBox = forall a. Agent a => AgentBox { unbox :: a }
deriving (Typeable)
instance Agent AgentBox where
agentId (AgentBox a) = agentId a
speciesId (AgentBox a) = speciesId a
bugTag :: String
bugTag = "Bug"
data Bug = Bug String
deriving (Typeable)
instance Agent Bug where
agentId (Bug name) = name
speciesId _ = bugTag
doSomethingWith :: AgentBox -> IO ()
doSomethingWith a = do
case cast a of
Just bug -> doBugStuff bug
Nothing -> return ()
doBugStuff :: Bug -> IO ()
doBugStuff a = putStrLn $ agentId a ++ " does bug stuff"