2013-05-02 20 views
94

Sto cercando di rendere i tipi di schermi ghci per le mie librerie il più intuitivi possibile, ma sto incontrando molte difficoltà quando si utilizzano funzionalità di tipo più avanzate.Perché ghci desugar elenca gli elenchi e digita le famiglie? Questo può essere disabilitato selettivamente?

Diciamo che ho questo codice in un file:

{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE DataKinds #-} 
{-# LANGUAGE TypeOperators #-} 

import GHC.TypeLits 

data Container (xs::[*]) = Container 

lo carico in ghci, poi digitare il seguente comando:

ghci> :t undefined :: Container '[String,String,String,String,String] 

Purtroppo, ghci mi dà l'piuttosto brutto looking:

:: Container 
     ((':) 
      * 
      String 
      ((':) 
      * String ((':) * String ((':) * String ((':) * String ('[] *)))))) 

ghci ha rimosso lo zucchero per stringhe di livello del tipo. C'è un modo per impedire a ghci di farlo e darmi solo la versione carina?


In una nota correlata, consente di dire a creare un livello di tipo Replicate funzione

data Nat1 = Zero | Succ Nat1 

type family Replicate (n::Nat1) x :: [*] 
type instance Replicate Zero x = '[] 
type instance Replicate (Succ n) x = x ': (Replicate n x) 

type LotsOfStrings = Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String 

Ora, quando chiedo ghci per un tipo di utilizzo LotsOfStrings:

ghci> :t undefined :: Container LotsOfStrings 

ghci è bello e mi dà il bel risultato:

Ma se chiedo per la versione Replicate d,

ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String) 

sostituti ghci in per la famiglia tipo, quando non ha fatto che per il tipo di sinonimo:

:: Container 
     ((':) 
      * 
      [Char] 
      ((':) 
      * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *)))))) 

Perché ghci facendo la sostituzione per tipo famiglia, ma non il sinonimo di tipo? C'è un modo per controllare quando ghci farà la sostituzione?

+7

Poiché i sinonimi di tipo sono concepiti esclusivamente per il consumo umano, non sostituiscono perché riconoscono di aver creato il sinonimo di tipo perché si voleva scrivere/vedere il tipo in quel modo. Rende la sostituzione con la famiglia tipo perché le famiglie tipo sono in realtà sul calcolo/deduzione di un tipo, non sulla visualizzazione. – AndrewC

+0

La soluzione al tuo problema è nella tua domanda - fai un sinonimo di tipo se vuoi abbreviare. – AndrewC

+0

@AndrewC Ok, non ho mai capito che era una delle distinzioni tra i sinonimi di tipi e le famiglie, ma questo ha senso. Ciò lascia comunque il desugaring degli elenchi di tipi. –

risposta

0
import GHC.TypeLits 

data Container (xs::[*]) = Container 

lo carico in ghci, poi digitare il seguente comando:

:t undefined :: Container '[String,String,String,String,String] 
+0

Quindi ...? Riceverete comunque il risultato di nuovo desugared suppongo, cioè 'String ((':) * String ((' :) * String ((':) * ...'. – leftaroundabout

2

La soluzione, che io sappia sta utilizzando: tipo. Per esempio,

ghci>: tipo (Container '[String, String, String, String, String])

Dà:

(Container' [String, String, String, String, String]) :: *

Mentre

ghci>: gentile!(Container '[String, String, String, String, String])

stamperanno qualcosa di simile:

Container

((' :)

* 
    [Char] 
    ((':) 
    * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *)))))) 

Ufficialmente, ovviamente, stai chiedendo a ghci una domanda diversa con kind, ma funziona. Uso di undefined :: i s una sorta di soluzione alternativa, quindi ho pensato che questo potesse essere sufficiente.

+0

Stavo solo usando 'undefined ::' per dare un semplice esempio: il vero problema è quando ricevi un messaggio di errore che ha un tipo di un elenco di migliaia di tipi diversi, occupa pagine per stamparlo ed è molto difficile da analizzare –

+0

Sì, abbastanza equo. l'ho capito, ti devo una risposta migliore – user2141650

2

Questo problema è stato risolto nel prossimo GHC 7.8.

GHC 7.6 stampa i tipi se un tipo di dati utilizza PolyKinds. Quindi vedi (':) * String ('[] *) anziché solo (':) String '[].

In GHC 7.8, i tipi non vengono più visualizzati per impostazione predefinita e il tipo di dati è stampato come un elenco, come previsto. È possibile utilizzare il nuovo flag -fprint-explicit-kinds per visualizzare i tipi espliciti come in GHC 7.6. Non conosco le ragioni per questo, presumibilmente i tipi espliciti sono stati pensati per essere un aiuto per comprendere PolyKinds.

Problemi correlati