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

Text.Printf с Data.Text?

Мне все время надо было распаковывать экземпляры 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 по умолчанию.

4b9b3361

Ответ 1

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


Я бы посмотрел на text-format пакет: он похож на Text.Printf, но специально разработан для Data.Text.Lazy.

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

  • Открывается класс Buildable, поэтому его можно расширить для поддержки новых типов параметров.
  • Он использует более простой подход к varargs, который уклоняется от проблем, возникающих в Text.Printf с доступом к возвращаемому значению.
  • Это должно быть намного быстрее, по нескольким причинам:
    • он никогда не преобразуется в неэффективное представление String;
    • он не создает промежуточные типы данных, в отличие от UPrintf в Text.Printf;
    • он использует пакет double-conversion для рендеринга Double и Float, который составляет около в 30 раз быстрее, чем методы Prelude.

Ответ 2

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

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

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

printt :: PrintType r => Text -> r
printt = printf . Data.Text.unpack

Ответ 3

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

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

Пример:

format ("Person name is " % text % ", age is " % hex) "Dave" 54