[ACCEPTED]-String interpolation in Haskell-haskell

Accepted answer
Score: 41

You can also just use Text.Printf which is included 3 in the GHC base libraries:

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

There are several 2 string interpolation packages on Hackage 1 http://hackage.haskell.org if you want fancier situations.

Score: 35

While the other posters here mention many 8 of the 'right' ways to do string interpolation, there 7 is a fancier way using quasiquotation and 6 the interpolatedstring-perl6 library:

{-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-}

import Text.InterpolatedString.Perl6 (qq)

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

In fact there is also an interpolatedstring-qq library which 5 offers a Ruby syntax.

{-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-}

import Text.InterpolatedString.QQ (istr)

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

That said, you probably 4 should just use show and ++ or concat to 3 glue together the strings

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

or

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

The latter tends 2 to look nicer, code-wise, when you are gluing 1 together a lot of string fragments.

Score: 19

Strings are really just lists. So you can 3 convert the number returned from length 2 and append it to your other string with 1 normal list functions:

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

Use format function from text-format-simple library:

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

0

Score: 4

Try this in ghci:

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

As you can see, the print function 4 accepts only one argument, while the code 3 above supplied two.

Instead, try this:

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

It's 2 joining the two strings with ++ and then prints 1 it.

Score: 4

Additionally to what others said you can 3 also use the monadic bind operator >> to combine 2 the two IO actions:

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

This is equivalent to 1 combining them with do-notation:

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

You could use something like

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

EDIT:

If 4 you want to do it like a function, to pass 3 any list and write its length, you could 2 do it this way:

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"

Of course, as commented above, you 1 could use putStrLn instead of print.

Score: 0

if you just want to debug stuff like:

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

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

this 4 QuasiQuoter might help:

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

the variables are 3 captured dynamically. I had written it while 2 learning Template Haskell, but debug does work 1 for debugging stuff during development.

Score: 0

I've posted about fmt formatting library recently 5 in my answer to another question. With this library you can write interpolation 4 like this:

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

Though, you might be also interested 3 in some TH library with Quasi Quoters:

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

Though, this 2 library is very slow in comparison with 1 fmt.

More Related questions