2016-03-25 2 views
0

Я определил эти типы данных, которые я пытаюсь создать и распечатать сейчас.Haskell - как изменить шоу, чтобы получить правильный вывод

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) 

Так я и создал эти Показать экземпляры

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" 

И я получаю этот выход (для уточнения я создал тип RightLinearGrammar и называется putStr $ show rlg):

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

Как я должен изменить код для получения лучшего результата, как этот?

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

ответ

1

show по умолчанию собирается дать вам кавычки строки и скобки списков. Если вы просто вернуться к конкатенации строк и соединения списков с запятыми или новыми строками, вы должны получить на выходе вы ожидаете:

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

Это работает. Не знал, что такие функции, как interperse и concat, существуют. – Dracke

+1

Я просто обновил его, чтобы использовать 'intercalate', который является сокращением для' concat $ intersperse xs xss' –

1

Вы либо должны заменить синонимы типа с newtypes и определить show на них сделайте то, что хотите, или, скорее всего, замените вызовы на show в своих экземплярах вызовами пользовательской функции форматирования.

Примечание: show действительно не подходит для того, что вы пытаетесь сделать, поскольку он обычно производит вывод, который вы можете вставить обратно в ghci и, возможно, следует ограничить его использование. Вы можете легко определить свою собственную функцию и использовать его как это:

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) 

Примечание: это будет довольно неэффективно для больших грамматик; вы можете захотеть переписать его как

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 
Смежные вопросы