2014-04-05 14 views
8

Data una variabile di tipo Dynamic, è possibile sfruttare le classi di tipi della variabile interna senza condizionamento del tipo esatto? Ad esempio, supponiamo di voler scrivere una funzione prettyShow. Se il tipo interno è un'istanza di Show, dovremmo utilizzare tale istanza; altrimenti, dovremmo utilizzare l'istanza della classe Dynamic. In codice, questo potrebbe essere simile:Combinazione di dati. Classi dinamiche e di tipo

prettyShow :: Dynamic -> String 
prettyShow x = case fromDynamic x :: (forall a. Show a => Maybe a) of 
    Nothing -> show x 
    Just y -> show y 

Edit: Dal momento che appare questo non può essere fatto direttamente, che cosa sono alcuni buoni soluzione alternativa che si può fare?

+0

In breve, no. Mi piacerebbe che queste informazioni fossero disponibili, ma le informazioni sulla classe sono andate perdute e rimane solo un typerep dopo la compilazione. –

+1

Ma sicuramente potrebbe esserci una grande tabella in memoria da qualche parte che associa ogni typerep con i suoi dizionari di classe. –

+2

... ma non c'è. –

risposta

6

Questo può essere fatto utilizzando l'implementazione di Dynamic nella libreria open-typerep (se si accetta l'uso di programmi generici e molte estensioni GHC).

{-# LANGUAGE TypeOperators #-} 

import Data.TypeRep 

type Types = BoolType :+: IntType :+: ListType 

x, y :: Dynamic Types 
x = toDyn [False,True] 
y = toDyn [1, 2 :: Int] 

test1 = show x 
test2 = show y 

La definizione di show è semplice, ed è possibile utilizzare la libreria per definire altre funzioni su valori dinamici.

Nell'esempio precedente ho utilizzato un universo di tipo chiuso Type. Ma usando i trucchi Data Type à la Carte puoi anche definire le funzioni per gli universi aperti. Ad esempio, lo stesso show è aperto.

prestazioni

Un simple benchmark dimostra che questo Dynamic è 2-3 volte più lento di Data.Dynamic nel base per il piccolo tipo universo utilizzato in precedenza. Aumentare l'universo a 30 costruttori di tipi lo rende un po 'più di 10 volte più lento.

Auto derivanti per i nuovi tipi

open-typerep supporta fare universi da un piccolo numero di tipi di rappresentazione predefiniti. In teoria, dovrebbe essere possibile utilizzare TemplateHaskell per eseguire automaticamente le rappresentazioni per i nuovi tipi, ma sarà difficile creare le istanze corrette per Witness e PWitness in quanto dipendono da quali altre istanze sono disponibili. (Witness viene utilizzato, ad esempio, dall'istanza Show per Dynamic.)

+0

Qual è la differenza di prestazioni tra questo e Data.Dynamic? La tua classe 'Typeable' può essere derivata automaticamente per tipi di cui non ho il controllo? –