2011-05-07 9 views
11

Quiero escribir una función con este tipo de firma:Haskell - Obtener TypeRep de instancia de tipo concreto

getTypeRep :: Typeable a => t a -> TypeRep 

donde el TypeRep será la representación de tipo para un , no por un t. Es decir, el compilador debe devolver automáticamente el tipo representación correcta en cualquier sitio de llamadas [a] getTypeRep, que tendrán tipos concretos de un .

Para añadir un poco de contexto, quiero crear un tipo de datos "tipo dinámico", con el giro que va a recordar el tipo de nivel superior, pero no su parámetro. Por ejemplo, yo quiero convertir MyClass un en dinámico MyClass, y la función anterior se puede utilizar para crear instancias de dinámico MyClass que almacenan una representación de parámetro de tipo un.

Respuesta

9

Bueno, ¿qué tal el uso de variables de tipo con ámbito para seleccionar el componente interno:

{-# LANGUAGE ExplicitForAll #-} 
{-# LANGUAGE ScopedTypeVariables #-} 

import Data.Dynamic 
import Data.Typeable 

getTypeRep :: forall t a . Typeable a => t a -> TypeRep 
getTypeRep _ = typeOf (undefined :: a) 

funciona para mí:

*Main> getTypeRep (Just()) 
() 
*Main> getTypeRep (Just 7) 
Integer 
*Main> getTypeRep ([True]) 
Bool 

diseño interesante.

8

En una nota tangencial a la solución de Don, observe que el código raramente requiere ScopedTypeVariables. Simplemente hace que la solución sea más limpia (pero menos portátil). La solución sin tipos de ámbito es:

{-# LANGUAGE ExplicitForAll #-} 
import Data.Typeable 

helper :: t a -> a 
helper _ = undefined 

getTypeRep :: forall t a. Typeable a => t a -> TypeRep 
getTypeRep = typeOf . helper 
Cuestiones relacionadas