2016-03-25 7 views
0

Ich habe diese Datentypen definiert, die ich jetzt erstellen und drucken möchte.Haskell - wie man die Show ändert, um die richtige Ausgabe zu erhalten

type TNonTerminal = String -- will be creating own ones where [A-Z] won't be enough 
type TTerminals = Char 
type TSymbols = String -- both terminals and nonterminals 

data Rule = Rule 
    { leftSide :: TNonTerminal 
    , rightSide :: [TSymbols] 
    } deriving (Eq) 

data RightLinearGrammar = RLG 
    { nonterminals :: [TNonTerminal] 
    , terminals :: [TTerminals] 
    , firstNonterminal :: TNonTerminal 
    , rules :: [Rule] 
    } deriving (Eq) 

Also habe ich auch diese anzeigen Instanzen

instance Show Rule where 
    show (Rule ls rs) = show ls ++ "->" ++ show rs ++ "\n" 

instance Show RightLinearGrammar where 
    show (RLG n t fn r) = show n ++ "\n" ++ show t ++ "\n" ++ show fn ++ "\n" ++ show r ++ "\n" 

Und ich bekomme diese Ausgabe (zur Verdeutlichung habe ich den Typ RightLinearGrammar und rief putStr $ show rlg):

["A","B"]   -- [TNonTerminal] 
"abc"    -- [TTerminals] 
"A"    -- TNonTerminal 
["A"->["aaB"]  -- 
,"A"->["ccB"] 
,"B"->["bB"]  -- [Rule] 
,"B"->["#"] 
]     -- 

Wie soll ich ändern der Code, um bessere Ergebnisse zu erzielen?

A,B 
a,b,c 
A 
A->aaB 
A->ccB 
B->bB 
B-># 

Antwort

1

show ist standardmäßig zu geben gehen Sie zitiert Strings und Klammern um Listen um. Wenn Sie nur Strings und Verbindungslisten mit Kommas oder Zeilenumbrüche gehen Sie zurück zu verketten, sollten Sie die Ausgabe erhalten Sie erwarten:

import Data.List (intercalate) 

instance Show Rule where 
    show (Rule ls rs) = ls ++ "->" ++ intercalate "," rs 

instance Show RightLinearGrammar where 
    show (RLG n t fn r) = intercalate "," n ++ "\n" ++ t ++ "\n" ++ fn ++ "\n" ++ (intercalate "\n" $ map show r) ++ "\n" 
+0

zu schreiben. Das funktioniert. Wusste nicht, dass solche Funktionen wie intersevers und concat existieren. – Dracke

+1

Ich habe es gerade aktualisiert, um 'intercalate' zu ​​verwenden, was eine Abkürzung für' concat $ intersperse xs xss' ist –

1

Sie müssen entweder Ihre Art Synonyme mit newtypes ersetzen und definieren show auf sie Tun Sie, was Sie wollen, oder ersetzen Sie die Aufrufe von show in Ihren Instanzen eher durch Aufrufe einer benutzerdefinierten Formatiererfunktion.

Hinweis: show ist wirklich nicht die richtige Funktion für das, was Sie versuchen zu tun, da es in der Regel Ausgabe produziert, die Sie in ghci einfügen könnten und wohl sollte auf diese Verwendung beschränkt werden. Sie könnten leicht eine eigene Funktion definieren und verwenden Sie es wie folgt aus:

formatRule :: Rule -> String 
formatRule (Rule ls rs) = ls ++ "->" ++ concat (intersperse "," rs) ++ "\n" 

formatRightLinearGrammar :: RightLinearGrammar -> String 
formatRightLinearGrammar (RLG n t fn r) = 
     concat (intersperse "," n) ++ "\n" 
    ++ intersperse ',' t ++ "\n" 
    ++ fn ++ "\n" 
    ++ concat (map formatRule r) 

Hinweis: Diese ziemlich ineffizient für große Grammatiken sein wird; Vielleicht möchten Sie darüber nachdenken, es als

formatRule :: Rule -> String -> String 
formatRule (Rule ls rs) = (ls++) . ("->"++) . concatDS (intersperse "," rs) . ("\n"++) 

formatRightLinearGrammar :: RightLinearGrammar -> String 
formatRightLinearGrammar (RLG n t fn r) = 
    concatDS (intersperse "," n) $ ("\n"++) $ 
    (intersperse ',' t ++) $ ("\n"++) $ 
    (fn++) $ ("\n"++) $ 
    foldr formatRule "" r 

concatDS ss s' = foldr (++) s' ss 
Verwandte Themen