Text.Printf与Data.Text?

时间:2012-06-09 20:30:19

标签: haskell

我厌倦了在打印出来进行调试之前一直解压缩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'

有什么想法吗?

EDITED

正如所建议的那样,试过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的所有建议,这不是开箱即用的。

4 个答案:

答案 0 :(得分:13)

警告:文本格式未维护,作者在2年内没有回复。请参阅其他答案。


我会查看text-format包:它类似于Text.Printf,但专为Data.Text.Lazy而设计。

文本格式还有一些优于Text.Printf的优点:

  • 公开了Buildable类,因此可以扩展它以支持新的参数类型。
  • 它使用一种更简单的方法来处理varargs,它可以回避Text.Printf accessing the return value中的问题。
  • 它应该快得多,原因有以下几点:
    • 它永远不会转换为低效的String表示;
    • 它不构建中间数据类型,与Text.Printf中的UPrintf不同;
    • 它使用double-conversion包来呈现DoubleFloat,这比Prelude的方法大约30 times faster

答案 1 :(得分:1)

来自文档:

  

HPprintfType类为hPrintf提供变量参数magic。它的实现有意在本模块中看不到。

虽然您可以使用TH生成HPrintfType实例(因为TH忽略了导出限制),但最简单的解决方案可能是printf'类型函数:

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

答案 2 :(得分:1)

另一个值得一试的套餐:formatting

  

基于组合器的类型安全格式(如printf()或FORMAT),用于Text。

     

示例:

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

答案 3 :(得分:1)

自从提出此问题以来,$cutend-1base库已更新为支持此问题。如果您具有 base> = 4.7.0.0 text> = 1.2.2.0 ,则OP的MWE实际上可以工作:

text

输出:

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

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