2012-05-24 16 views
7

Necesito un mapa que pueda contener valores arbitrarios siempre que sus tipos sean de la misma clase de tipo. Mi primera aproximación ingenua era algo como esto:Mapa heterogéneo

type HMap = forall a . MyClass a => M.Map Int a 

pero no parece funcionar: el siguiente código da un error de compilación:

testFunction :: (forall a . MyClass a => M.Map Int a) -> Int -> IO() 
testFunction m i = do 
    case M.lookup i m of 
     Nothing -> return() 
     Just v -> someActionFromMyClass v >> putStrLn "OK" 


Ambiguous type variable `a0' in the constraint: 
    (MyClass a0) arising from a use of `m' 
Probable fix: add a type signature that fixes these type variable(s) 
In the second argument of `M.lookup', namely `m' 
In the expression: (M.lookup i m) 
In a stmt of a 'do' block: 
    case (M.lookup i m) of { 
    Nothing -> return() 
    Just v -> someActionFromMyClass v >> putStrLn "OK" } 

pensé que necesito colección heterogénea especial, pero extrañamente No pude encontrar nada en Google, excepto this, pero esta biblioteca parece un poco desaliñada y antigua. ¿Cuál es la forma de hacerlo correctamente (es de esperar sin otras bibliotecas, solo con extensiones GHC)?

Respuesta

9

Intente utilizar un tipo existencial adecuado.

{-# LANGUAGE ExistentialQuantification #-} 

data Elem = forall e. C e => Elem e 

type HMap = Map Int Elem 
+0

¡Muchas gracias! Es una pena que no lo haya conseguido yo mismo. Creo que tengo que dormir más de lo que lo hago ahora) –