代码之家  ›  专栏  ›  技术社区  ›  emi

在Haskell中删除字符串双引号

  •  3
  • emi  · 技术社区  · 16 年前

    此函数生成简单的.dot文件,用于使用Graphviz可视化自动机转换函数。它的主要目的是调试大量自动生成的转换(例如,拉丁动词的屈折变化)。

    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”不是我用来存储屈折变化的实际形式,但是这种形式确实包含一两个字符串。我怎么能告诉哈斯克尔:当你 show 一个字符串值,不要双引号吗?

    4 回复  |  直到 16 年前
        1
  •  7
  •   wlangstroth    16 年前

    看看Martin Erwig是如何处理同一个问题的数据图归纳Graphviz先生:

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

    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
    

    (当然,请查看上下文并根据自己的代码进行调整)

        2
  •  2
  •   ADEpt    16 年前

    使用dotgen包-它有特殊的保护措施,以防止禁止字符潜入属性值。

        3
  •  1
  •   Paul Johnson    16 年前

    您可以这样定义自己的类型类:

    class GShow a where
       gShow :: a -> String
       gShow = show
    
    instance GShow String where
       show = id
    
    instance GShow Integer
    instance GShow Char
    -- And so on for all the types you need.
    

    “gShow”的默认实现是“show”,因此不需要为每个实例都使用“where”子句。但是你需要所有的实例,这有点拖沓。

    或者你可以用 overlapping instances . 我认为(尽管我还没有尝试过)这将允许您用一行代码替换使用默认“gShow”的实例列表:

    instance (Show a) => GShow a
    

    其思想是,对于重叠的实例,编译器将选择可用的最具体的实例。因此,对于字符串,它将选择字符串实例而不是更一般的实例,而对于其他所有对象,一般实例是唯一匹配的实例。

        4
  •  -1
  •   Matt Ellen Bipin Vayalu    16 年前

    看起来有点难看,但你可以申请 filter show t

    filter (/='"') (show t)