Ich versuche, die Ghci-Typanzeigen für meine Bibliotheken so intuitiv wie möglich zu gestalten, aber ich habe viele Schwierigkeiten, wenn ich erweiterte Typfunktionen verwende.
Angenommen, ich habe diesen Code in einer Datei:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeLits
data Container (xs::[*]) = Container
Ich lade es in ghci hoch und gebe dann den folgenden Befehl ein:
ghci> :t undefined :: Container '[String,String,String,String,String]
Leider sieht mir ghci ziemlich hässlich aus:
:: Container
((':)
*
String
((':)
* String ((':) * String ((':) * String ((':) * String ('[] *))))))
ghci hat den Zucker für Saiten auf Typebene entfernt. Gibt es eine Möglichkeit, ghci daran zu hindern, dies zu tun und mir nur die hübsche Version zu geben?
Nehmen wir an, ich erstelle eine Replicate
Funktion auf Typebene
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
Nun, wenn ich ghci nach einem Typ frage, der Folgendes verwendet LotsOfStrings
:
ghci> :t undefined :: Container LotsOfStrings
ghci ist nett und gibt mir das hübsche Ergebnis:
undefined :: Container LotsOfStrings
Aber wenn ich nach der Replicate
d-Version frage ,
ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)
ghci ersetzt die Typfamilie, wenn dies für das Typensynonym nicht der Fall ist:
:: Container
((':)
*
[Char]
((':)
* [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))
Warum ersetzt ghci die Typenfamilie, nicht aber das Typensynonym? Gibt es eine Möglichkeit zu kontrollieren, wann ghci die Substitution durchführen wird?
[Char]
und manchmal als angezeigtString
?String->String
, wird der Typ ihres Ergebnisses als angezeigtString
. Wenn es jedoch einen Typ aus Stücken konstruieren muss, wie z. B. in"abc"
(was dasselbe ist wie'a':'b':'c':[]
), gibt es kein Synonym, das beibehalten werden muss. Das ist reine Spekulation.String
mit Typvariablenf a
oder vereinheitlicht[a]
wird, er[Char]
aus ähnlichen Gründen wie später angezeigt wird .Antworten:
Die Problemumgehung, die ich kenne, ist: kind. Zum Beispiel,
Gibt:
Während
Wird so etwas drucken:
Offiziell stellen Sie ghci natürlich eine andere Frage
kind
, aber es funktioniert. Die Verwendungundefined ::
ist sowieso eine Art Problemumgehung, daher dachte ich, dass dies ausreichen könnte.quelle
undefined ::
, um ein einfaches Beispiel zu geben. Das eigentliche Problem ist, wenn Sie eine Fehlermeldung erhalten, die einen Typ einer Liste von tausend verschiedenen Typen enthält. Es braucht Seiten, um es auszudrucken, und ist sehr schwer zu analysieren.Dies ist in der kommenden GHC 7.8 behoben.
GHC 7.6 druckt Arten, wenn ein Datentyp PolyKinds verwendet. Sie sehen also
(':) * String ('[] *)
statt nur(':) String '[]
.In GHC 7.8 werden Arten standardmäßig nicht mehr angezeigt und Ihr Datentyp wird wie erwartet als Liste gedruckt. Mit dem neuen Flag können
-fprint-explicit-kinds
Sie explizite Arten wie in GHC 7.6 anzeigen. Ich kenne die Gründe dafür nicht. Vermutlich explizite Arten sollten dazu beitragen, PolyKinds zu verstehen.quelle
Ich lade es in ghci hoch und gebe dann den folgenden Befehl ein:
quelle
String ((':) * String ((':) * String ((':) * ...
.