2016-09-01 4 views
2

Dies ist eine vereinfachte Version meines Problems.Phantom-Typen in Haskell

Ich habe eine rekursive Datenstruktur (Stream1). Wenn ich Phantom-Typen einführte (Stream a), funktioniert eine rekursive Beschreibung (d. H. T1) nicht mehr. Auf der anderen Seite funktioniert t2 gut, indem eine unendliche Struktur erstellt wird, da Stream1 direkt verwendet wird. Ich brauche den Konstruktor preI, wie in t1. Was vermisse ich? Ich brauche t1, um sich wie t2 zu verhalten - das heißt, einen unendlichen Strom zurückgeben.

data Stream a = Stream Stream1 
    deriving (Eq, Show) 

data Stream1 = PreI Integer Stream1 
    deriving (Eq, Show) 

preI :: Integer -> Stream Int -> Stream Int 
preI n (Stream s) = Stream (PreI n s) 

t1 :: Stream Int 
t1 = let x = preI 0 x 
    in x 

t2 :: Stream Int 
t2 = let x = PreI 0 x 
    in Stream x 
+0

Sie haben nicht gesagt, was das Problem ist, aber versuchen Sie 'Stream' in einen' newtype' (anstelle von 'data') zu ändern. – melpomene

+0

(Ich aktualisierte die Beschreibung des Problems) Ja, das scheint das Problem gelöst zu haben. Danke vielmals! – ami

Antwort

6
preI :: Integer -> Stream Int -> Stream Int 
preI n (Stream s) = ... 
    -- ^^^^^^^^^^ 

Dieser Musterabgleich zwingt das Argument, bevor eine Ausgabe erzeugt wird. Für Streams ist das schlecht, da es den niedrigsten Fixpunkt im unteren Bereich (Nicht-Terminierung) anstatt in einem unendlichen Stream hält.

Sie können einen faulen/unwiderlegbaren Muster versuchen passende statt:

preI :: Integer -> Stream Int -> Stream Int 
preI n ~(Stream s) = Stream (PreI n s) 
    --^

Dies bedeutet im Wesentlichen:

preI :: Integer -> Stream Int -> Stream Int 
preI n z = Stream (PreI n s) 
    where s = case z of Stream x -> x 

, die zuerst die Stream, PreI in der Ausgabe erzeugt, und erst später beginnt, seinen Eingang auszupacken (was passiert, wenn s verwendet wird).

Oder, noch besser, ändern Stream von einem data zu einem newtype: auf diese Weise wird die Mustererkennung immer faul sein. In der Tat, mit newtype haben wir nicht mehr zur Laufzeit ein Wrapping, und Mustererkennung ist eigentlich ein No-Op.

+0

Danke chi. Das Ändern von 'Stream' von' data' nach 'newtype' hat den Zweck erfüllt. – ami