Подтвердить что ты не робот

Как написать многострочные строки в 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.
4b9b3361

Ответ 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 является моим фаворитом для этой цели.