Dekonstruowanie typu egzystencjalnego
Używam typu egzystencjalnego jako opakowania. W punkcie mojego kodu, w którym znam typ zamknięty, chcę zrobić coś, co jest specyficzne dla zamkniętego typu. To najbliższy, jaki mogę uzyskać:
{-# LANGUAGE ExistentialQuantification #-}
class Agent a where
agentId :: a -> String
speciesId :: a -> String
-- plus other functions that all agents support
-- | A wrapper allowing my daemon to read and write agents of any species.
-- (Agents are stored in files that contain a tag so I know which function
-- to call to read the agent.)
data AgentBox = forall a. Agent a => AgentBox { unbox :: a }
instance Agent AgentBox where
agentId (AgentBox a) = agentId a
speciesId (AgentBox a) = speciesId a
-- plus other functions that all agents support
bugTag :: String
bugTag = "Bug"
data Bug = Bug String
instance Agent Bug where
agentId (Bug name) = name
speciesId _ = bugTag
doSomethingWith :: AgentBox -> IO ()
doSomethingWith a = do
if speciesId a == bugTag
then do
-- Now I know it's a bug, and I want to do something bug-specific
doBugStuff2 a
return ()
else return ()
doBugStuff :: Bug -> IO ()
doBugStuff a = putStrLn $ agentId a ++ " does bug stuff"
doBugStuff2 AgentBox{unbox=a} = doBugStuff (a `asTypeOf` model) -- line 39
where model = undefined :: Bug
Błąd, który otrzymuję to:
Amy30.hs:39:45:
Could not deduce (a ~ Bug)
from the context (Agent a)
bound by a pattern with constructor
AgentBox :: forall a. Agent a => a -> AgentBox,
in an equation for `doBugStuff2'
at Amy30.hs:39:13-29
`a' is a rigid type variable bound by
a pattern with constructor
AgentBox :: forall a. Agent a => a -> AgentBox,
in an equation for `doBugStuff2'
at Amy30.hs:39:13
In the first argument of `asTypeOf', namely `a'
In the first argument of `doBugStuff', namely
`(a `asTypeOf` model)'
In the expression: doBugStuff (a `asTypeOf` model)
Failed, modules loaded: none.
Jak mogę to osiągnąć? Z góry dziękuję za wszelkie sugestie.