【问题标题】:How can I write multiline strings in Haskell?如何在 Haskell 中编写多行字符串?
【发布时间】:2014-05-20 01:47:57
【问题描述】:

假设我有这个带换行符的字符串文字:

file :: String
file = "the first line\nthe second line\nthe third line"

有没有办法这样写?

file :: String
file = "the first line
        the second line
        the third line"

上面的尝试导致了这个错误:

factor.hs:58:33:
    lexical error in string/character literal at character '\n'
Failed, modules loaded: none.

【问题讨论】:

  • 假设有一种方法,它不会添加空格来实现缩进吗?
  • @JonathanFischoff 见my answer

标签: haskell


【解决方案1】:

你可以这样写多行字符串

x = "This is some text which we escape \
      \   and unescape to keep writing"

打印为

"This is some text which we escape   and unescape to keep writing"

如果你想把它打印成两行

x = "This is some text which we escape \n\
      \   and unescape to keep writing"

打印为

This is some text which we escape
    and unescape to keep writing

【讨论】:

    【解决方案2】:

    我不相信 Haskell 有一个简单的方法可以做到这一点而不诉诸 quasiquoting 或其他东西。但是,您可以通过使用下面的 unlines 函数来获得您想要的大部分内容。但是,这将导致在您的最后一行之后出现一个换行符,您可能关心也可能不关心。

    file :: String
    file = unlines [
        "the first line",
        "the second line",
        "the third line"
        ]
    

    【讨论】:

    • 这有运行时成本,而我或 nschoe 的回答中的文字则不是这种情况
    • 是的,我知道这一点。我刚刚读到核心希望 GHC 能优化掉那个调用,但没有这样的运气。不过,我在一些地方看到过这种模式。
    • +1:这可能是规范的解决方案。如果说成本甚至是一个问题,那么模板 Haskell 解决了运行时成本。如果您不想要尾随换行符,请使用 intercalate "\n" 而不是 unlines
    • 如果您像 Thomas Eding 建议的那样使用嵌入,请记住 import Data.List。我猜想导入的要求是为什么我看到unlines 的使用频率高于intercalate
    • @jozefg "过早的优化是万恶之源",运行时成本很小,因为懒惰,只有 O(1),如果你对此有性能问题,不要使用 [Char ],ByteString 或 Text 可能是想要的。
    【解决方案3】:

    在 Haskell 中,您可以通过以反斜杠 \ 结束它并以另一个 \ 开始换行符来键入多行字符串,就像这样:

    file :: String
    file = "the first line\n\  
        \the second line\n\  
        \the third line\n"  
    

    【讨论】:

    • 这不会像 OP 想要的那样添加换行符
    • 您需要显式添加换行符转义符才能正常工作。正如你所写,这将不起作用。
    • 是的,当然,对不起。我更专注于向您展示如何在 Haskell 中添加多行字符串,但我忘了写 '\n'。现在修好了。谢谢。
    • 不错。最佳答案恕我直言,因为它不仅显示要做什么,而且解释它一般是如何工作的。真的很好。
    【解决方案4】:

    很多时候这个facality被称为heredocs。 Haskell 没有 heredocs。

    但是,有几个包使用 GHC 的 QuasiQuotes 扩展来实现这一点。

    这是我使用的一个:http://hackage.haskell.org/package/interpolatedstring-perl6-0.9.0/docs/Text-InterpolatedString-Perl6.html

    您的示例如下所示:

    file = [q|
    the first line
    the second line
    the third line
    |]
    

    【讨论】:

      【解决方案5】:

      前段时间我发布了一个名为"neat-interpolation" 的库来解决多行字符串和使用QuasiQoutes 扩展的插值问题。与竞争对手相比,它的主要优势是对空格的智能管理,它可以处理内插的多行字符串。以下是其工作原理的示例。

      执行以下操作:

      {-# LANGUAGE QuasiQuotes, OverloadedStrings #-}
      
      import NeatInterpolation (text)
      import qualified Data.Text.IO
      
      f :: Text -> Text -> Text
      f a b = 
        [text|
          function(){
            function(){
              $a
            }
            return $b
          }
        |]
      
      main = Data.Text.IO.putStrLn $ f "1" "2"
      

      会产生这个(注意缩进与声明相比减少了):

      function(){
        function(){
          1
        }
        return 2
      }
      

      现在让我们用多行字符串参数来测试它:

      main = Data.Text.IO.putStrLn $ f 
        "{\n\
        \  indented line\n\
        \  indented line\n\
        \}" 
        "{\n\
        \  indented line\n\
        \  indented line\n\
        \}"
      

      我们得到

      function(){
        function(){
          {
            indented line
            indented line
          }
        }
        return {
          indented line
          indented line
        }
      }
      

      请注意它如何巧妙地保留变量占位符所在行的缩进级别。标准的插值器会弄乱所有的空白并产生类似下面的东西:

          function(){
            function(){
              {
        indented line
        indented line
      }
            }
            return {
        indented line
        indented line
      }
          }
      

      【讨论】:

      • 有趣 - 但由于需要语言扩展,因此不适用于 GHC 7.4.x。 (MultiWayIf, LambdaCase.)
      • @MathematicalOrchid 是的。在我的大多数库中,我不支持 7.6 以上的 GHC。
      【解决方案6】:

      Multi-line strings in Haskell 中提供的准引用示例。

      {-# LANGUAGE QuasiQuotes #-}
      import Text.RawString.QQ
      
      multiline :: String
      multiline = [r|<HTML>
      <HEAD>
      <TITLE>Auto-generated html formated source</TITLE>
      <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
      </HEAD>
      <BODY LINK="800080" BGCOLOR="#ffffff">
      <P> </P>
      <PRE>|]
      

      raw-strings-qq 是我目前最喜欢的。

      【讨论】:

        猜你喜欢
        • 2011-12-17
        • 2013-05-29
        • 1970-01-01
        • 2018-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多