19

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 的所有建议,这并不是开箱即用的。

4

4 回答 4

13

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


我会看一下text-format包:它类似于Text.Printf,但专门为Data.Text.Lazy.

文本格式还有其他一些优点Text.Printf

  • 该类Buildable是公开的,因此可以对其进行扩展以支持新的参数类型。
  • 它对可变参数使用了一种更简单的方法,从而回避Text.Printf访问返回值时遇到的问题。
  • 它应该更快,有几个原因:
    • 它永远不会转换为低效的String表示;
    • 它不构建中间数据类型,不像UPrintf;Text.Printf
    • 它使用双转换包来渲染DoubleFloat,比 Prelude 的方法快大约 30 倍。
于 2012-06-09T23:27:44.757 回答
3

自从提出这个问题以来,basetext库已经更新以支持这一点。如果您有base >= 4.7.0.0text >= 1.2.2.0,那么 OP 的 MWE 实际上可以工作:

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

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

输出:

$ ghci
GHCi, version 8.2.2: http://www.haskell.org/ghc/  :? for help
Prelude> :l test.hs
[1 of 1] Compiling Main             ( test.hs, interpreted )
Ok, one module loaded.
*Main> main
Input: abc
*Main> 
Leaving GHCi.
于 2018-06-27T07:32:20.593 回答
1

从文档中:

HPrintfType 类为 hPrintf 提供了变量参数魔法。从这个模块中故意看不到它的实现。

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

printt :: PrintType r => Text -> r
printt = printf . Data.Text.unpack
于 2012-06-09T20:53:51.450 回答
1

另一个值得一试的包:格式化

文本的基于组合器的类型安全格式(如 printf() 或 FORMAT)。

例子:

format ("Person's name is " % text % ", age is " % hex) "Dave" 54
于 2016-11-02T11:37:42.293 回答