String Haskell中的字符串插值

String Haskell中的字符串插值,string,haskell,String,Haskell,我想编写将输出的代码: length [1,2,3] => 3 在Ruby中,我可以这样做: puts "length [1,2,3] => #{[1,2,3].length}" 以下尝试是Haskell失败的 Prelude Data.List> print "length [1,2,3]" "length [1,2,3]" Prelude Data.List> print (length [1,2,3]) 3 Prelude Data.List> pr

我想编写将输出的代码:

length [1,2,3] => 3   
在Ruby中,我可以这样做:

puts "length [1,2,3] => #{[1,2,3].length}"
以下尝试是Haskell失败的

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>
Prelude Data.List>打印“长度[1,2,3]”
“长度[1,2,3]”
序曲数据列表>打印(长度[1,2,3])
3.
前奏曲数据列表>打印“长度[1,2,3]”(长度[1,2,3])
:1:0:
无法匹配预期的类型'Int->t'
针对推断类型'IO()'
在表达式中:打印“长度[1,2,3]”(长度[1,2,3])
在“it”的定义中:
它=打印“长度[1,2,3]”(长度[1,2,3])
序曲数据。列表>

您可以使用

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

如果您想像函数一样传递任何列表并写入其长度,可以这样做:

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"

当然,如上所述,您可以使用
putStrLn
而不是打印。

字符串实际上只是列表。因此,您可以转换从length返回的数字,并使用常规列表函数将其附加到其他字符串中:

print $ "length [1,2,3] " ++ show (length [1,2,3])
在ghci中尝试以下操作:

Prelude> :t print
print :: (Show a) => a -> IO ()
如您所见,
print
函数只接受一个参数,而上面的代码提供了两个参数

相反,请尝试以下方法:

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

它用
++
连接两个字符串,然后打印出来。

除其他人所说的之外,您还可以使用一元绑定操作符
>
组合两个IO操作:

putStr "length [1,2,3]: " >> print (length [1,2,3])
这相当于将它们与do符号相结合:

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

虽然这里的其他海报提到了许多进行字符串插值的“正确”方法,但有一种更奇特的方法使用准旋转和

事实上,还有一个提供Ruby语法的库

{-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-}

import Text.InterpolatedString.QQ (istr)

main = putStrLn [$istr| length [1,2,3] => #{length [1,2,3]} |]
也就是说,您可能应该使用show和++或concat将字符串粘合在一起

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

当您将大量字符串片段粘合在一起时,后者在代码方面看起来更好。

您也可以使用GHC基本库中包含的:

> let format s = printf "length %s => %d\n" (show s) (length s)
> format [1,2,3]
length [1,2,3] => 3
如果您想要更高级的情况,Hackage上有几个字符串插值软件包。

使用库中的函数:


如果您只想调试以下内容:

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

inc 2
-- prints "1+x = 3"
-- returns 3
这个准实验者可能会有帮助:

{-# 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
变量是动态捕获的。我是在学习模板Haskell时写的,但是
debug
在开发过程中可以调试东西。

我最近在中发布了关于格式化库的内容。使用此库,您可以编写如下插值:

> "There are "+|n|+" million bicycles in "+|city|+"."
不过,您可能也对某些具有准引用人的TH库感兴趣:


尽管如此,与
fmt

相比,这个库的速度非常慢。有三种方法可以将它们写在一行中吗?顺便说一句,在字符串上使用print将使用引号(和转义)打印它。请尝试使用putStr或putStrLn按原样打印字符串。为什么使用
concat
++
比使用quasiquetes更好?每次使用模板haskell时,编译器都必须在编译时加载所有依赖项。它可能相当慢。我倾向于不为诸如字符串插值之类的琐碎方便而花费这些成本,当替代方法的长度几乎相同时,并且当我使用的近似Haskell语法的准旋转无法解析我需要的某些语法结构时,我不太可能要求我完全重构代码。@VladtheImpala,另一个原因是,每一个准程序员都要求读者理解一种新的语言,所以他们不一定能马上看到bug。如果我的项目经常使用QuasiQueter,我只会使用它,因此我希望开发人员知道它是如何工作的。您可以使用
interlate
,而不是
interlate
,这样可以避免手动插入分隔空格:
main=putStrLn$interlate”“[“length[1,2,3]=>,show$length(1,2,3)]
inc :: Int -> Int
inc x = [debug|1+x|]

inc 2
-- prints "1+x = 3"
-- returns 3
{-# 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
> "There are "+|n|+" million bicycles in "+|city|+"."