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|+"."