Text.Printf с Data.Text?

17

Мне было больно распаковывать Data.Text экземпляров все время, прежде чем распечатывать их для отладки и думали просто использовать Text.Printf для этого. К сожалению, я не мог заставить это работать:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Text
import Text.Printf

--instance PrintfArg Text where
--  toUPrintf = toUPrintf . unpack

main :: IO ()
main = do
  let input :: Text = "abc"
  printf "Input: %s\n" input

Ошибка:

src/Main.hs:12:3:
    No instance for (PrintfArg Text)
      arising from a use of 'printf'
    Possible fix: add an instance declaration for (PrintfArg Text)
    In a stmt of a 'do' block: printf "Input: %s" input
    In the expression:
      do { let input :: Text = "abc";
           printf "Input: %s" input }
    In an equation for 'main':
        main
          = do { let input :: Text = ...;
                 printf "Input: %s" input }

После расторжения объявления экземпляра:

src/Main.hs:7:7:
    'toUPrintf' is not a (visible) method of class 'PrintfArg'
src/Main.hs:7:19: Not in scope: 'toUPrintf'

Любые идеи?

отредактированы

Как и было предложено, попробовал TH, по-прежнему нет:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
import Data.Text
import Language.Haskell.TH
import Text.Printf

runQ [d| instance PrintfArg Text where toUPrintf = toUPrintf . unpack|]

main :: IO ()
main = do
  let input :: Text = "abc"
  printf "Input: %s\n" input

Ошибка:

src/Main.hs:9:40:
    'toUPrintf' is not a (visible) method of class 'PrintfArg'
src/Main.hs:9:52: Not in scope: 'toUPrintf'

Помощь! Удивительно, что это не работает из коробки, учитывая все советы по использованию Data.Text по умолчанию.

    
задан Skirmantas Kligys 09.06.2012 в 22:30
источник
  • Получить пакет printf и экспортировать класс PrintfArg и использовать его вместо обычного пакета. –  augustss 10.06.2012 в 04:37
  • @augustss: printf находится в базе, а не отдельный пакет. И, возможно, достаточно материала можно экспортировать, чтобы пользователи могли создавать свои собственные экземпляры PrintfArg? –  John L 10.06.2012 в 07:05
  • Я добавлю модуль Text.Printf.Internal, чтобы показать все типы и типы типов. –  augustss 10.06.2012 в 08:52

3 ответа

11

ПРЕДУПРЕЖДЕНИЕ: текстовый формат не поддерживается, нет ответа от автора через 2 года. См. Другие ответы.

Я бы посмотрел текстовый формат : он похож на Text.Printf , но конкретно для Data.Text.Lazy .

Есть еще несколько преимуществ текстового формата над Text.Printf :

  • Buildable , поэтому он может быть расширен для поддержки новых типов параметров.
  • Он использует более простой подход к varargs, который оборачивает проблемы, которые возникают в Text.Printf с доступ к возвращаемому значению .
  • Это должно быть намного быстрее, по нескольким причинам:
    • он никогда не преобразуется в неэффективное представление String ;
    • он не создает промежуточные типы данных, в отличие от UPrintf в Text.Printf ;
    • он использует пакет double-conversion для рендеринга Double и Float , который составляет около < a href="http://www.serpentine.com/blog/2011/06/29/here-be-dragons-advances-in-problems-you-didnt-even-know-you-had/"> 30 раз быстрее , чем методы Prelude.
ответ дан reinerp 10.06.2012 в 01:27
  • Спасибо, я закончил делать TF.print «Input: {} \ n" $ TF.Only input. –  Skirmantas Kligys 10.06.2012 в 01:39
  • Как вы делаете классический материал для форматирования printf, например% .02f? –  Nikita Volkov 10.02.2013 в 03:36
  • Есть ли документация о том, как Data.Text.Format.Format читает экземпляр IsString? Могу ли я использовать стандартные символы формата printf? –  John F. Miller 09.08.2016 в 18:28
  • У них есть проблема, открытая с 2014 года по поводу отсутствия документации, не тратьте свое время –  Jonny Leeds 18.12.2017 в 18:13
1

Из документации:

  

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

Хотя вы можете использовать TH для генерации экземпляров HPrintfType (поскольку TH игнорирует ограничения на экспорт), самым простым решением, вероятно, является функция printf' :

printt :: PrintType r => Text -> r
printt = printf . Data.Text.unpack
    
ответ дан Thomas M. DuBuisson 09.06.2012 в 22:53
  • Не работает: src / Main.hs: 12: 3: Нет экземпляра для (PrintfArg Text), связанного с использованием «printt». Возможное исправление: добавьте объявление экземпляра для (PrintfArg Text). В строке a 'do' block: printt Вход "Вход:% s" В выражении: do {let input :: Text="abc"; printt Вход «Вход:% s» В уравнении для «main»: main = do {let input :: Text = ...; printt Вход «Вход:% s»} –  Skirmantas Kligys 09.06.2012 в 23:05
  • О, как меня глупо. Очевидно, вы хотите, чтобы строка формата была полезной. Я думаю, вам нужно добавить экземпляр в модуль printf или использовать TH. –  Thomas M. DuBuisson 09.06.2012 в 23:30
1

Еще один пакет, который стоит проверить: форматирование

  

Форматирование на основе комбинатора (например, printf () или FORMAT) для текста.

     

Пример:

format ("Person's name is " % text % ", age is " % hex) "Dave" 54
    
ответ дан Johannes Gerer 02.11.2016 в 12:37
  • кажется, что он имеет зависимости C-библиотеки? Некоторые двойные преобразования ... –  Paul-AG 24.11.2017 в 13:42
  • Это больше не зависит от двойного преобразования или текстового формата. –  Christopher Done 20.12.2017 в 15:26