2009-08-12 10 views
13

Quiero escribir el código que va de salida:interpolación de cadenas en Haskell

length [1,2,3] => 3 

En Ruby, yo podría hacerlo como:

puts "length [1,2,3] => #{[1,2,3].length}" 

Después de intentarlo es Haskell no ...

Prelude Data.List> print "length [1,2,3]" 
"length [1,2,3]" 
Prelude Data.List> print (length [1,2,3]) 
3 
Prelude Data.List> print "length [1,2,3]" (length [1,2,3]) 

<interactive>:1:0: 
    Couldn't match expected type `Int -> t' 
    against inferred type `IO()' 
In the expression: print "length [1,2,3]" (length [1, 2, 3]) 
In the definition of `it': 
     it = print "length [1,2,3]" (length [1, 2, 3]) 
Prelude Data.List> 
+8

Por cierto, al imprimir en una cadena se imprimirá con comillas (y se escapó). Pruebe putStr o putStrLn para imprimir la cadena tal como está. –

Respuesta

15

Las cadenas son realmente solo listas. Lo que puede convertir el número de regresar de longitud y añadirlo a su otra cadena con funciones de lista normales:

print $ "length [1,2,3] " ++ show (length [1,2,3]) 
3

Puede usar algo como

putStr "length [1,2,3] => " 
print (length [1,2,3]) 

EDIT:

Si desea hacerlo como una función, para pasar cualquier lista y escribir su longitud, que podría hacerlo de esta manera:

print_length :: Show a => [a] -> IO() 
print_length xs = print ("length " ++ show xs ++ " => " ++ show (length xs)) 

Main> print_length [1,2,3,4,5] 
"length [1,2,3,4,5] => 5" 

Main> print_length [] 
"length [] => 0" 

Por supuesto, como se ha comentado anteriormente, podría usar putStrLn en lugar de imprimir.

+0

¿Hay tres maneras de escribirlas en una línea? – pierrotlefou

4

probar este en ghci:

Prelude> :t print 
print :: (Show a) => a -> IO() 

Como se puede ver, la función print sólo acepta un argumento, mientras que el código anterior proporcionó dos.

En su lugar, intente esto:

putStrLn ("length [1,2,3] => " ++ show (length [1,2,3])) 

Se une las dos cadenas con ++ y luego lo imprime.

3

Adicionalmente a lo que otros dijeron también se puede utilizar el operador se unen monádico >> combinar las dos acciones IO:

putStr "length [1,2,3]: " >> print (length [1,2,3]) 

Esto es equivalente a la combinación de ellos con do-notación:

do putStr "length [1,2,3]: " 
    print (length [1,2,3]) 
28

Mientras que los otros carteles aquí mencionan muchas de las formas "correctas" de hacer la interpolación de cuerdas, hay una manera más elegante de usar cuasiquotación y el interpolatedstring-perl6 library:

{-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-} 

import Text.InterpolatedString.Perl6 (qq) 

main = putStrLn [$qq| length [1,2,3] => ${length [1,2,3]} |] 

De hecho, también hay una biblioteca interpolatedstring-qq que ofrece una sintaxis de Ruby.

{-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-} 

import Text.InterpolatedString.QQ (istr) 

main = putStrLn [$istr| length [1,2,3] => #{length [1,2,3]} |] 

Dicho esto, es probable que sólo debe utilizar espectáculo y concat ++ o para pegar entre sí las cadenas

main = putStrLn $ "length [1,2,3] => " ++ show (length [1,2,3]) 

o

main = putStrLn $ concat ["length [1,2,3] => ", show $ length (1,2,3)] 

esta última tiende a mirar más agradable, código- sabio, cuando estás pegando muchos fragmentos de cuerda.

+0

¿Por qué es mejor usar 'concat' o' ++ 'que QuasiQuotes? –

+4

Cada vez que usa template-haskell su compilador tiene que cargar todas las dependencias en tiempo de compilación. Puede ser bastante lento Tiendo a no incurrir en ese costo por una conveniencia trivial como la interpolación de cadenas, cuando la alternativa es casi la misma longitud, y es poco probable que requiera refactorizar completamente mi código cuando la cuasiquotación que se aproxima a la sintaxis de Haskell que estoy usando no puede analizar alguna construcción sintáctica que necesito. –

+0

@VladtheImpala, otra razón es que cada QuasiQuoter requiere que el lector entienda un nuevo idioma, por lo que no necesariamente será capaz de ver los errores de inmediato. Solo usaría un QuasiQuoter si mi proyecto lo usaba mucho, por lo que puedo esperar que los desarrolladores sepan cómo funciona. – povman

28

Usted también puede utilizar Text.Printf que se incluye en las bibliotecas de base de GHC:

> let format s = printf "length %s => %d\n" (show s) (length s) 
> format [1,2,3] 
length [1,2,3] => 3 

Hay varios paquetes de interpolación de cadenas en Hackage http://hackage.haskell.org si quieres situaciones más elegantes.

5

Uso format función de text-format-simple biblioteca:

import Text.Format 
format "length [1,2,3] => {0}" [show $ length [1,2,3]] 
0

si sólo quieren cosas de depuración como:

inc :: Int -> Int 
inc x = [debug|1+x|] 

inc 2 
-- prints "1+x = 3" 
-- returns 3 

este QuasiQuoter podría ayudar:

{-# LANGUAGE TemplateHaskell #-} 
module Template where 
import Language.Haskell.TH 
import Language.Haskell.TH.Quote 
import Language.Haskell.TH.Syntax 
import Language.Haskell.Meta.Parse 
import Debug.Trace 

-- | e.g. f x = [debug|1+x|] 
debug :: QuasiQuoter 
debug = QuasiQuoter traceExp undefined undefined undefined 

-- | e.g. traceExp "1+x" -> [| trace "1+x = $([|1+x|])" (1+x) |] 
-- (or something) 
traceExp :: String -> Q Exp 
traceExp s = [|(trace $(showExp s) $(parseE s))|] 

-- | e.g. showExp "1+x" -> [| "1+x" ++ " = " ++ show (1+x) |] 
showExp :: String -> Q Exp 
showExp s = [|($(stringE s) ++ " = " ++ show $(parseE s))|] 

-- | e.g. parseE "1+x" -> (UInfixE (LitE (IntegerL 1)) (VarE +) (VarE x)) 
parseE :: String -> Q Exp 
parseE = return . either (const undefined) id . parseExp 

-- $ cabal install haskell-src-exts 
-- $ cabal install haskell-src-meta 

las variables son capturados dinamicamente. Lo había escrito mientras aprendía Template Haskell, pero debug funciona para depurar cosas durante el desarrollo.

0

He publicado sobre fmt la biblioteca de formato recientemente en my answer to another question. Con esta biblioteca puede escribir interpolación de la siguiente manera:

> "There are "+|n|+" million bicycles in "+|city|+"." 

sin embargo, usted podría ser también interesado en alguna biblioteca TH con cotizantes Cuasi:

https://hackage.haskell.org/package/interpolate-0.1.1/docs/Data-String-Interpolate.html

Sin embargo, esta biblioteca es muy lento en comparación con fmt.

Cuestiones relacionadas