Spec-Zone.ru › Haskell 7

Text.Printf

Авторские права (c) Lennart Augustsson и Bart Massey 2013
Лицензия BSD-стиль (см. файл LICENSE в этом дистрибутиве)
Поддержка Bart Massey <bart@cs.pdx.edu>
Устойчивость предварительная
Портируемость портируемая
Safe Haskell Безопасный
Язык Haskell2010

Содержание

  • Функции вывода
  • Расширение для новых типов
    • Обработка специфичных для типа модификаторов
    • Стандартные форматировщики
    • Генерация ошибок
  • Внутренние детали реализации

Описание

Форматировщик, подобный C printf(3). Эта версия была расширена Bart Massey в соответствии с рекомендациями John Meacham и Simon Marlow <http://comments.gmane.org/gmane.comp.lang.haskell.libraries/4726>, чтобы поддерживать расширяемое форматирование для новых типов данных. Она также была расширена для поддержки почти всего синтаксиса C printf(3).

Функции вывода

printf :: PrintfType r => String -> r Исходный код

Форматирует переменное число аргументов с использованием строки форматирования в стиле C. Результатом является либо String или (IO a) (должно быть (IO '()'), но система типов Haskell затрудняет это).

Строка форматирования состоит из обычных символов и *спецификаций преобразования*, которые определяют, как форматировать один из аргументов printf в строке вывода. Спецификация форматирования вводится символом %; этот символ может быть экранирован в строке форматирования с помощью %%. Спецификация форматирования заканчивается *символом форматирования*, который предоставляет основную информацию о том, как форматировать значение. Остальная часть спецификации преобразования является необязательной. В порядке следования могут быть символы флагов, спецификатор ширины, спецификатор точности и символы модификатора, специфичные для типа.

В отличие от C printf(3), форматирование этого printf определяется типом аргумента; форматирование является типом-специфичным. Типы, которые форматируются printf "из коробки", это:

  • Integral типы, включая Char
  • String
  • RealFloat типы

printf также расширяется для поддержки других типов: см. ниже.

Спецификация преобразования начинается с символа %, за которым следуют ноль или более следующих флагов:

   -      left adjust (default is right adjust)
   +      always use a sign (+ or -) for signed conversions
   space  leading space for positive numbers in signed conversions
   0      pad with zeros rather than spaces
   #      use an \"alternate form\": see below

Когда оба флага указаны, - переопределяет 0 и + переопределяет пробел. Отрицательный спецификатор ширины в спецификации преобразования * рассматривается как положительный, но подразумевает флаг левого выравнивания.

«Альтернативная форма» для преобразований радикса без знака такая же, как в C printf(3):

   %o           prefix with a leading 0 if needed
   %x           prefix with a leading 0x if nonzero
   %X           prefix with a leading 0X if nonzero
   %b           prefix with a leading 0b if nonzero
   %[eEfFgG]    ensure that the number contains a decimal point

Любые флаги необязательно следуют за спецификатором ширины:

   num    field width
   *      as num, but taken from argument list

Ширина поля является минимальной, а не максимальной: она будет расширена по мере необходимости, чтобы избежать искажения значения.

Любая ширина поля необязательно следует за спецификатором точности:

   .num   precision
   .      same as .0
   .*     as num, but taken from argument list

Отрицательная точность рассматривается как 0. Значение точности зависит от типа преобразования.

   Integral    minimum number of digits to show
   RealFloat   number of digits after the decimal point
   String      maximum number of characters

Точность для целочисленных типов достигается путём заполнения нулями. Если и точность, и заполнение нулями указаны для целочисленного поля, заполнение нулями игнорируется.

Любая точность за целочисленными типами необязательно следует за модификатором ширины; единственное применение этого модификатора — установить неявный размер операнда для преобразования отрицательного операнда в беззнаковый:

   hh     Int8
   h      Int16
   l      Int32
   ll     Int64
   L      Int64

Спецификация заканчивается символом форматирования:

   c      character               Integral
   d      decimal                 Integral
   o      octal                   Integral
   x      hexadecimal             Integral
   X      hexadecimal             Integral
   b      binary                  Integral
   u      unsigned decimal        Integral
   f      floating point          RealFloat
   F      floating point          RealFloat
   g      general format float    RealFloat
   G      general format float    RealFloat
   e      exponent format float   RealFloat
   E      exponent format float   RealFloat
   s      string                  String
   v      default format          any type

Спецификатор «%v» предоставляется для всех встроенных типов и должен предоставляться для форматировщиков пользовательских типов тоже. Он выбирает «лучшее» представление для данного типа. Для встроенных типов спецификатор «%v» преобразуется следующим образом:

   c      Char
   u      other unsigned Integral
   d      other signed Integral
   g      RealFloat
   s      String

Несоответствие между типами аргументов и строкой форматирования, а также любые другие синтаксические или семантические ошибки в строке форматирования, приведут к возникновению исключения во время выполнения.

Обратите внимание, что форматирование RealFloat типов в настоящее время немного отличается от C printf(3), следуя вместо этого showEFloat, showFFloat и showGFloat (и их альтернативных версий showFFloatAlt и showGFloatAlt). Это трудно исправить: исправленные версии форматировали бы несовместимым образом. В любом случае поведение Haskell, как правило, более разумно, чем поведение C. Краткое изложение некоторых ключевых различий:

  • Haskell printf никогда не использует стандартную «6-значную» точность, используемую в C printf.
  • Haskell printf обрабатывает спецификатор «точности» как указывающий на количество цифр после десятичной точки.
  • Haskell printf выводит экспоненту чисел в формате e без ненужного знака плюс и с минимально возможным количеством цифр.
  • Haskell printf будет помещать ноль после десятичной точки, когда это возможно.
Примеры
  > printf "%d\n" (23::Int)
  23
  > printf "%s %s\n" "Hello" "World"
  Hello World
  > printf "%.2f\n" pi
  3.14

hPrintf :: HPrintfType r => Handle -> String -> r Исходный код

Аналогично printf, за исключением того, что вывод осуществляется через указанный Handle. Тип возврата ограничен (IO a).

Расширение для новых типов

Это printf может быть расширено для форматирования типов, отличных от тех, которые предоставляются по умолчанию. Это делается путём присвоения PrintfArg и предоставления formatArg для типа. Можно предоставить parseFormat для обработки модификаторов, специфичных для типа, но экземпляр по умолчанию обычно является лучшим выбором.

Например:

instance PrintfArg () where
  formatArg x fmt | fmtChar (vFmt 'U' fmt) == 'U' =
    formatString "()" (fmt { fmtChar = 's', fmtPrecision = Nothing })
  formatArg _ fmt = errorBadFormat $ fmtChar fmt

main :: IO ()
main = printf "[%-3.1U]\n" ()

выводит "[() ]". Обратите внимание на использование formatString для удобной обработки спецификаций форматирования поля.

class PrintfArg a where Исходный код

Класс типов printf-форматируемых значений. Метод formatArg принимает значение и описание формата поля и либо возвращает ошибку из-за плохого описания, либо возвращает ShowS в качестве результата. Экземпляр по умолчанию parseFormat ожидает отсутствие модификаторов: это обычный случай. Минимальный экземпляр: formatArg.

Минимальное полное определение

formatArg

Методы

formatArg :: a -> FieldFormatter Исходный код

С: 4.7.0.0

parseFormat :: a -> ModifierParser Исходный код

С: 4.7.0.0

Экземпляры

type FieldFormatter = FieldFormat -> ShowS Исходный код

Это тип форматировщика поля, реифицированного над его аргументом.

С: 4.7.0.0

data FieldFormat Source

Описание форматирования поля для formatArg. Смотрите UNIX printf(3) для описания того, как работает форматирование поля.

С: 4.7.0.0

Конструкторы

FieldFormat

Поля

fmtWidth :: Maybe Int

Общая ширина поля.

fmtPrecision :: Maybe Int

Вспомогательный спецификатор ширины поля.

fmtAdjust :: Maybe FormatAdjustment

Тип выравнивания или заполнения.

fmtSign :: Maybe FormatSign

Требовать знак «плюс» для положительных чисел.

fmtAlternate :: Bool

Указывает «альтернативный формат». См. printf(3) для подробностей, которые варьируются в зависимости от спецификации аргумента.

fmtModifiers :: String

Символы, непосредственно слева от fmtChar в формате и принятые типом parseFormat. Обычно пустая строка.

fmtChar :: Char

Символ формата printf был вызван. formatArg должно завершиться ошибкой, если этот символ не соответствует типу. Обычно используется множество различных символов формата для одного типа.

data FormatAdjustment Source

Выравнивание слева или нулевое заполнение поля. Они взаимно исключают друг друга, причем LeftAdjust имеет приоритет.

С: 4.7.0.0

Конструкторы

LeftAdjust
ZeroPad

data FormatSign Source

Как обрабатывать знак числового поля. Они взаимно исключают друг друга, причем SignPlus имеет приоритет.

С: 4.7.0.0

Конструкторы

SignPlus
SignSpace

vFmt :: Char -> FieldFormat -> FieldFormat Source

Заменить символ формата 'v' заданным символом формата по умолчанию в FieldFormat. Удобство для типов, реализованных пользователем, которые должны поддерживать «%v».

С: 4.7.0.0

Обработка специфичных для типа модификаторов

В маловероятном случае, когда желаемы символы-модификаторы определенного типа для пользовательского типа, можно предоставить ModifierParser для обработки этих символов. Результирующие модификаторы будут отображаться в FieldFormat для использования типоспецифическим форматировщиком.

type ModifierParser = String -> FormatParse Source

Тип функции, которая будет анализировать символы-модификаторы из строки формата.

С: 4.7.0.0

data FormatParse Source

«Парсер формата» проходит по символам модификаторов, специфичных для типа аргумента, чтобы найти основной символ формата. Это тип его результата.

С: 4.7.0.0

Конструкторы

FormatParse

Поля

fpModifiers :: String

Любые найденные модификаторы.

fpChar :: Char

Основной символ формата.

fpRest :: String

Остаток строки формата.

Стандартные форматировщики

Эти форматировщики для стандартных типов предоставляются для удобства при написании форматировщиков для новых типов: общий шаблон заключается в перебрасывании в formatString или formatInteger для выполнения большей части обработки формата для нового типа.

formatString :: IsChar a => [a] -> FieldFormatter Source

Форматировщик для значений String.

С: 4.7.0.0

formatChar :: Char -> FieldFormatter Source

Форматировщик для значений Char.

С: 4.7.0.0

formatInt :: (Integral a, Bounded a) => a -> FieldFormatter Source

Форматировщик для значений Int.

С: 4.7.0.0

formatInteger :: Integer -> FieldFormatter Source

Форматировщик для значений Integer.

С: 4.7.0.0

formatRealFloat :: RealFloat a => a -> FieldFormatter Source

Форматировщик для значений RealFloat.

С: 4.7.0.0

Вызов ошибок

Эти функции используются во внутренней реализации для вызова различных ошибок и экспортируются для использования типоспецифическими форматировщиками.

errorBadFormat :: Char -> a Source

Вызывает perror для указания неизвестного символа формата для данного типа.

С: 4.7.0.0

errorShortFormat :: a Source

Вызывает perror для указания того, что строка формата завершилась преждевременно.

С: 4.7.0.0

errorMissingArgument :: a Source

Вызывает perror для указания отсутствия аргумента в списке аргументов.

С: 4.7.0.0

errorBadArgument :: a Source

Вызывает perror для указания ошибки типа или подобной в заданном аргументе.

С: 4.7.0.0

perror :: String -> a Source

Вызывает error с префиксом, специфичным для printf, в строке сообщения.

С: 4.7.0.0

Внутренности реализации

Эти типы необходимы для реализации обработки переменного числа аргументов для printf и hPrintf. Их реализация намеренно не видна из этого модуля. Если вы попытаетесь передать аргумент типа, который не является экземпляром соответствующего класса в printf или hPrintf, компилятор сообщит об этом как об отсутствии экземпляра PrintfArg. (Все экземпляры PrintfArg являются экземплярами PrintfType.)

class PrintfType t Source

Класс PrintfType предоставляет магию переменных аргументов для printf. Его реализация намеренно не видна из этого модуля. Если вы попытаетесь передать аргумент типа, который не является экземпляром этого класса в printf или hPrintf, компилятор сообщит об отсутствии экземпляра PrintfArg.

Минимальное полное определение

spr

Экземпляры

IsChar c => PrintfType [c]
(~) * a () => PrintfType (IO a)
(PrintfArg a, PrintfType r) => PrintfType (a -> r)

class HPrintfType t Source

Класс HPrintfType предоставляет магию переменных аргументов для hPrintf. Его реализация намеренно не видна из этого модуля.

Минимальное полное определение

hspr

Экземпляры

(~) * a () => HPrintfType (IO a)
(PrintfArg a, HPrintfType r) => HPrintfType (a -> r)

Этот класс необходим как обходной путь совместимости Haskell98 из-за отсутствия FlexibleInstances.

class IsChar c where Source

Этот класс, имеющий только один экземпляр, используется как обходной путь для того, что String, как конкретный тип, не допускается как экземпляр типа класса. IsChar экспортируется для обратной совместимости.

Методы

toChar :: c -> Char Source

Since: 4.7.0.0

fromChar :: Char -> c Source

Since: 4.7.0.0

Экземпляры

IsChar Char

© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/7.10.3/docs/html/libraries/base-4.8.2.0/Text-Printf.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API