Haskell - 如何更改节目以获得正确的输出

时间:2016-03-25 16:56:34

标签: 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)

所以我也创建了那些Show实例

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"

我得到了这个输出(为了澄清我创建了Type 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->#

2 个答案:

答案 0 :(得分: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"

答案 1 :(得分: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