Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing String double-quotes in Haskell

This function generates simple .dot files for visualizing automata transition functions using Graphviz. It's primary purpose is debugging large sets of automatically generated transitions (e.g., the inflections of Latin verbs).

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" ++ ")\" ]"

where wrap, wrapSp and mapSp are formatting functions, as is deltaTuples.

The problem is that formatGraph retains double quotes around Strings, which causes errors in Graphviz. E.g., when I print unlines $ prepGraph to a file, I get things like:

0 -> 1 [ label = "('a', "N. SF")" ];

instead of

0 -> 1 [ label = "('a', N. SF)" ];

(However, "Null" seems to work fine, and outputs perfectly well). Now of course the string "N. SF" isn't the actual form I use to store inflections, but that form does include a String or two. So how can I tell Haskell: when you show a String values, don't double-quote it?

like image 440
emi Avatar asked Apr 06 '26 05:04

emi


2 Answers

Check out how Martin Erwig handled the same problem in Data.Graph.Inductive.Graphviz:

http://hackage.haskell.org/packages/archive/fgl/5.4.2.3/doc/html/src/Data-Graph-Inductive-Graphviz.html

The function you're looking for is "sq" at the bottom:

sq :: String -> String
sq s@[c]                     = s
sq ('"':s)  | last s == '"'  = init s
            | otherwise      = s
sq ('\'':s) | last s == '\'' = init s
            | otherwise      = s
sq s                         = s

(check out the context and adapt for your own code, of course)

like image 126
wlangstroth Avatar answered Apr 09 '26 11:04

wlangstroth


Use dotgen package - it has special safeguards in place to prevent forbidden chars from sneaking into attribute values.

like image 29
ADEpt Avatar answered Apr 09 '26 11:04

ADEpt