缩进字符串中的所有行

Kev*_*ner 6 string haskell

我有一些Show定义了自定义实例的类型。它们的结构如下:

data TopLevel = TopLevel SndLevel
data SndLevel = SndLevel Int

instance Show SndLevel where
  show (SndLevel i) = "SndLevel: \n\t" ++ (show i)
Run Code Online (Sandbox Code Playgroud)

当它们出现在我的输出中时,我的Showfor实例SndLevel产生看起来很漂亮的字符串:

SndLevel: 
  5
Run Code Online (Sandbox Code Playgroud)

我想为此创建一个Show实例,topLevel以便TopLevel (SndLevel 5)在打印到终端时看起来像这样:

TopLevel
  SndLevel
    5
Run Code Online (Sandbox Code Playgroud)

我希望找到一个内置在Haskell中的函数,该函数将添加"\t"在字符串的开头以及"\n"该字符串出现的每个位置之前。

最好的解决方法,我发现将沿着答案的线条去这个职位。在这种情况下,我将替换"\n""\t\n"

我假设我不是第一个需要在Haskell中使用Show实例来按层次组织数据的人,所以我想知道是否有一种更惯用的方式来完成此任务。我的问题有更好的解决方案吗?

ps:我意识到对于我上面使用的示例数据类型而言,这种打印不是最好的。我要为其编写实例的实际数据类型是产品类型,因此当它们延伸到一行时,它们的读取效果不佳。考虑到这一点,如果有一种流行的方法来解决这种问题,而无需使用换行符和制表符,那也可以解决我的问题。

Wil*_*sem 11

我们可以通过使用lines :: String -> [String]unlines :: [String] -> String从a String移到Strings 列表再返回来解决此问题。

在这两者之间,我们可以利用来map :: (a -> b) -> [a] -> [b]在所有行之前添加一个制表符(a String是的列表Char),例如:

indent :: String -> String
indent = unlines . map ('\t' :) . lines
Run Code Online (Sandbox Code Playgroud)

例如:

Prelude> indent (show (SndLevel 5))
"\tSndLevel: \n\t\t5\n"
Run Code Online (Sandbox Code Playgroud)

我们可以在我们的确定指标使用Show两个SndLevelTopLevel这样的:

instance Show SndLevel where
    show (SndLevel n) = "SndLevel:" ++ '\n' : indent (show n)

instance Show TopLevel where
    show (TopLevel n) = "TopLevel:" ++ '\n' : indent (show n)
Run Code Online (Sandbox Code Playgroud)

因此,这给了我们:

Prelude> print (TopLevel (SndLevel 5))
TopLevel:
    SndLevel:
        5
Run Code Online (Sandbox Code Playgroud)

话虽如此,a Show通常用于显示对象的表示形式,该对象通常可以“注入”到编译器/解释器中。使用缩进的想法一点也不坏,但是也许为此定义自己的类型类是有意义的。您可以使用传递和更新的参数来跟踪缩进级别,从而提高该类型类的效率。

此外,还有几个漂亮打印 ”库[Reddit]可以很好地打印对象的结构。因此,与其“ 重新发明轮子 ”,不如使用Reddit页面上列出的软件包之一。