Как написать многострочные строки в Haskell?
Скажем, у меня есть этот строковый литерал с разрывами строк:
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.
Ответы
Ответ 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
Некоторое время назад я выпустил библиотеку с именем "опрятная интерполяция" , чтобы решить проблему многострочных строк и интерполяция с использованием расширения 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
}
}
Ответ 3
В Haskell вы можете вводить многострочные строки, завершая его обратным слэшем \
и начиная новую строку с помощью другого \
, так же:
file :: String
file = "the first line\n\
\the second line\n\
\the third line\n"
Ответ 4
Я не верю, что у Haskell есть простой способ сделать это, не прибегая к квазикрутке или чем-то еще. Однако вы можете в основном получить то, что хотите, используя функцию unlines, как показано ниже. Однако это приведет к появлению новой строки после вашей последней строки, которую вы можете или не заботитесь.
file :: String
file = unlines [
"the first line",
"the second line",
"the third line"
]
Ответ 5
Много раз эта способность упоминается как 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
|]
Ответ 6
Пример квазивокации, представленный в Многострочные строки в 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 является моим фаворитом для этой цели.