2011-05-07 5 views
11

Voglio scrivere una funzione con questa firma tipo:Haskell - ricevo TypeRep da esempio tipo concreto

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

dove il TypeRep sarà la rappresentazione tipo per un, non per t un. In altre parole, il compilatore dovrebbe restituire automaticamente la corretta rappresentazione del tipo in qualsiasi sito di chiamata [su ], con tipi di calcestruzzo per a.

Per aggiungere un contesto, voglio creare un tipo di dati "Tipo dinamico", con la torsione che ricorderà il tipo di primo livello, ma non il suo parametro. Per esempio, io voglio girare MyClass un in dinamica MyClass, e la funzione di cui sopra sarà utilizzato per creare istanze di dinamica MyClass che memorizzano una rappresentazione del parametro type un.

risposta

9

Beh, che dire usando le variabili di tipo di ambito per selezionare il componente interna:

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

import Data.Dynamic 
import Data.Typeable 

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

funziona per me:

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

Design interessante.

8

Su una nota tangenziale alla soluzione di Don, notare che raramente il codice richiede ScopedTypeVariables. Rende solo la soluzione più pulita (ma meno portatile). La soluzione senza tipi di ambito è:

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

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

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

Questa funzione (ora) esiste in Data.TypeabletypeRep