2012-06-09 19 views
17

Me cansé de desempaquetar instancias Data.Text todo el tiempo antes de imprimirlas para la depuración y pensé simplemente usar Text.Printf para eso. Por desgracia, no pude hacer que funcione:Text.Printf with Data.Text?

{-# 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 

El error:

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 } 

Después descomentando la declaración de la instancia:

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

¿Alguna idea?

editado

Como se sugirió, intentó TH, sigue sin ir:

{-# 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 

error:

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

Ayuda! Es sorprendente que esto no funcione de la caja dado todos los consejos para usar Data.Text por defecto.

+0

obtener el paquete printf y exportación de la clase PrintfArg y el uso que en lugar del paquete de costumbre. – augustss

+1

@augustss: printf está en la base, no es un paquete separado. ¿Y tal vez se podrían exportar suficientes cosas para que los usuarios puedan crear sus propias instancias de PrintfArg? –

+1

Agregaré un módulo Text.Printf.Internal para exponer todas las clases de tipos y tipos implicados. – augustss

Respuesta

11

ADVERTENCIA : el formato de texto no se mantiene, no hay respuesta del autor en 2 años. Ver otras respuestas


me vería en el paquete text-format: es similar a Text.Printf, pero diseñado específicamente para Data.Text.Lazy.

Hay algunas otras ventajas del formato de texto sobre Text.Printf:

  • Buildable La clase está expuesto, por lo que puede ser extendida para soportar nuevos tipos de parámetros.
  • Utiliza un enfoque más simple para varargs, que esquiva los problemas que uno tiene en Text.Printf con accessing the return value.
  • que debería ser mucho más rápido, por varias razones:
    • nunca se convierte en la representación String ineficiente;
    • no construye tipos de datos intermedios, a diferencia de UPrintf en Text.Printf;
    • usa el paquete double-conversion para representar Double y Float, que es aproximadamente 30 times faster que los métodos de Prelude.
+0

Gracias, terminé haciendo 'TF.print" Entrada: {} \ n "$ TF.Olyly input'. –

+9

¿Cómo se hace con el formato clásico de printf como '% .02f'? –

+0

¿Hay documentación sobre cómo Data.Text.Format.Format lee su instancia de IsString? ¿Puedo usar los caracteres estándar de formato 'printf' con él? –

1

De la documentación:

The HPrintfType class provides the variable argument magic for hPrintf. Its implementation is intentionally not visible from this module.

Mientras que usted podría usar TH generar instancias HPrintfType (porque TH hace caso omiso de las restricciones de exportación) la solución más sencilla es probablemente una función printf' Tipo:

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

no funciona bien: src/Main.hs: 12: 3: Ningún caso de (PrintfArg texto) gracias a la utilización de 'Printt' solución posible: añadir una declaración de la instancia de (PrintfArg texto) En un stmt de un bloque 'do': printt Entrada "Input:% s" En la expresión: do {let input :: Text = "abc"; printt "Entrada:% s" entrada} En una ecuación para 'main': main = do {let input :: Text = ...; printt "Input:% s" input} –

+0

Ohh, qué tonto de mi parte. Desea que la cadena de formato sea útil obviamente. Bueno, creo que necesitarás agregar la instancia al módulo printf o usar TH. –

1

Otro paquete vale la pena ver: formatting

Combinator-based type-safe formatting (like printf() or FORMAT) for Text.

Example:

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

parece que tiene dependencias de librerías C? Alguna conversión doble ... –

+0

Ya no depende de la doble conversión ni del formato de texto. –