如何在Haskell中编写多行字符串?

liu*_*tao 56 haskell

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

file :: String
file = "the first line\nthe second line\nthe third line"
Run Code Online (Sandbox Code Playgroud)

有没有办法像这样写?

file :: String
file = "the first line
        the second line
        the third line"
Run Code Online (Sandbox Code Playgroud)

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

factor.hs:58:33:
    lexical error in string/character literal at character '\n'
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

Dan*_*zer 83

您可以编写多行字符串

x = "This is some text which we escape \
      \   and unescape to keep writing"
Run Code Online (Sandbox Code Playgroud)

打印为

"This is some text which we escape   and unescape to keep writing"
Run Code Online (Sandbox Code Playgroud)

如果您希望将其打印为两行

x = "This is some text which we escape \n\
      \   and unescape to keep writing"
Run Code Online (Sandbox Code Playgroud)

打印为

This is some text which we escape
    and unescape to keep writing
Run Code Online (Sandbox Code Playgroud)


Nik*_*kov 35

前段时间我发布了一个名为"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"
Run Code Online (Sandbox Code Playgroud)

将产生这一点(注意减少的缩进与声明的方式相比):

function(){
  function(){
    1
  }
  return 2
}
Run Code Online (Sandbox Code Playgroud)

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

main = Data.Text.IO.putStrLn $ f 
  "{\n  indented line\n  indented line\n}" 
  "{\n  indented line\n  indented line\n}" 
Run Code Online (Sandbox Code Playgroud)

我们得到了

function(){
  function(){
    {
      indented line
      indented line
    }
  }
  return {
    indented line
    indented line
  }
}
Run Code Online (Sandbox Code Playgroud)

注意它如何巧妙地保留了变量占位符所在行的缩进级别.标准内插器会弄乱所有空格并产生如下内容:

    function(){
      function(){
        {
  indented line
  indented line
}
      }
      return {
  indented line
  indented line
}
    }
Run Code Online (Sandbox Code Playgroud)

  • @MathematicalOrchid 是的。在我的大多数库中,我不支持早于 7.6 的 GHC。 (3认同)

nsc*_*hoe 19

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

file :: String
file = "the first line\n\  
    \the second line\n\  
    \the third line\n"  
Run Code Online (Sandbox Code Playgroud)


Var*_*ath 11

我不相信Haskell有一个简单的方法来做到这一点,而不诉诸于quasiquoting或其他东西.但是,你可以通过使用如下所示的unlines函数获得你想要的东西.但是,这将导致在您的最后一行之后换行,您可能会或可能不会关心.

file :: String
file = unlines [
    "the first line",
    "the second line",
    "the third line"
    ]
Run Code Online (Sandbox Code Playgroud)

  • 这会产生运行时成本,而我或 nschoe 的答案中的文字情况并非如此 (4认同)
  • @jozefg"过早优化是所有邪恶的根源",运行时成本很小,只有O(1)因为懒惰,如果你有性能问题,不要使用[Char],ByteString或Text可能是什么想要. (4认同)
  • +1:这可能是规范的解决方案.模板Haskell解决了运行时成本,如果所述成本首先是一个问题.如果你不想要尾随换行符,请使用`intercalate'\n"`而不是`unlines`. (3认同)
  • 是的,我知道这一点。我只是读到核心希望 GHC 会优化掉那个调用,但没有这样的运气。不过,我在一些地方看到过这种模式。 (2认同)
  • 如果您正在使用Thomas Eding建议的插入,请记住`import Data.List`.我猜测导入的要求是为什么我看到`unlines`比`intercalate`更经常使用. (2认同)

Jon*_*off 9

很多时候,这种方式被称为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
|]
Run Code Online (Sandbox Code Playgroud)


pal*_*lik 5

在 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>|]
Run Code Online (Sandbox Code Playgroud)

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