这个函数使用Graphviz生成简单的.dot文件,用于可视化自动机转移函数。它的主要目的是调试大量自动生成的转换(例如,拉丁动词的屈折形式)。
prepGraph :: ( ... ) => NFA c b a -> [String]
prepGraph nfa = "digraph finite_state_machine {"
: wrapSp "rankdir = LR"
: wrapSp ("node [shape = circle]" ++ (mapSp (states nfa \\ terminal nfa)))
: wrapSp ("node [shape = doublecircle]" ++ (mapSp $ terminal nfa))
: formatGraph nfa ++ ["}"]
formatGraph :: ( ... ) => NFA c b a -> [String]
formatGraph = map formatDelta . deltaTuples
where formatDelta (a, a', bc) = wrapSp (mkArrow a a' ++ " " ++ mkLabel bc)
mkArrow x y = show x ++ " -> " ++ show y
mkLabel (y, z) = case z of
(Just t) -> "[ label = \"(" ++ show y ++ ", " ++ show t ++ ")\" ]"
Nothing -> "[ label = \"(" ++ show y ++ ", " ++ "Null" ++ ")\" ]"
其中wrap
,wrapSp
和mapSp
是格式化函数,deltaTuples
也是。
问题在于formatGraph
会保留字符串周围的双引号,这会导致在Graphviz中出现错误。例如,当我将unlines $ prepGraph
打印到文件中时,我得到了以下内容:
0 -> 1 [ label = "('a', "N. SF")" ];
替代
0 -> 1 [ label = "('a', N. SF)" ];
然而,“Null”似乎可以正常工作,并且输出完美。 当然,“N. SF”字符串不是我用于存储变化的实际形式,但是该形式确实包括一个或两个字符串。 那么我该如何告诉Haskell:当你显示String值时,请不要加上双引号?