如何在Haskell中打印标识符或绑定的名称?
我想打印Haskell中“变量”的名称和值。该名称在编译时已知!有没有比下面的例子更好的方法如何在Haskell中打印标识符或绑定的名称?,haskell,metaprogramming,code-inspection,Haskell,Metaprogramming,Code Inspection,我想打印Haskell中“变量”的名称和值。该名称在编译时已知!有没有比下面的例子更好的方法 module V (e, c, eV, h, hbar, nm, k, viewAllConstants) where import Text.Printf c = 2.99792458e8::Double e = exp(1) eV = 1.602176565e-19 h = 6.62606957e-34 hbar = h/(2*pi) nm = 1e-9 k = 1.3806488e-23 view
module V
(e, c, eV, h, hbar, nm, k, viewAllConstants) where
import Text.Printf
c = 2.99792458e8::Double
e = exp(1)
eV = 1.602176565e-19
h = 6.62606957e-34
hbar = h/(2*pi)
nm = 1e-9
k = 1.3806488e-23
viewAllConstants = do
putStr ((\a b -> (foldl (++) "" ( zipWith (++) a (map (printf " = %.2e\n") b))))
["c", "e", "eV", "h", "hbar", "nm", "k"]
[c, e, eV, h, hbar, nm, k] )
请在您的答案中发布一个工作代码示例(runhaskell) 正如@PeterHall所说:
在Lisp中,数据和代码之间的区别是模糊的,所有内容在运行时都是可检查和动态的。在Haskell中,所有类型和绑定名称都会在编译时删除,这允许进行大量优化 换句话说,该名称在运行时不为人所知 此外,这些不是“变量”,而是常量,或者如前所述,是绑定。因此,访问绑定的名称没有意义,因为它永远不会更改 正如@MathematicalOrchid所建议的,可能有一个模板Haskell解决方案,尽管它可能只是相对有用的 关于打印绑定的更好方法,请尝试以下方法:
import Control.Monad (forM_)
viewAllConstants = forM_ (\(a, b) -> putStrLn (a ++ " = " ++ show b))
$ zip ["c", "e", "eV", "h", "hbar", "nm", "k"]
[ c, e, eV, h, hbar, nm, k ]
我觉得你对自己真正想要的东西有点困惑。标识符
c
的名称就是“c”
;打印出来没有问题
我假设您真正想要的是消除模块中[“c”、“e”、“eV”、“h”、“hbar”、“nm”、“k”]
和[c、e、eV、h、hbar、nm、k]
之间的重复。具体来说,你打算怎么做?然后我们可以讨论它是否能在Haskell中工作
可能会归结为以下两种情况中的一种或两种
eval
。如果您保留列表[“c”、“e”、“eV”、“h”、“hbar”、“nm”、“k”]
,您可能希望计算这些字符串以找出相应变量的值。虽然可以在程序中潜在地嵌入Haskell解释器,但在运行时不一定存在名称“c”
,“e”
。。。正如其他人所指出的那样,您不能从字符串“c”
转到值2.99792458e8
[c,e,eV,h,hbar,nm,k]
,并希望找到一些神奇的方法来恢复字符串“c”
,“e”
。。。从它。但这也是不可能的<代码>[c,e,eV,h,hbar,nm,k]只是一个双倍列表,由于c=2.99792458e8
,我们也有[c,e,eV,h,hbar,nm,k]=[2.99792458e8,e,eV,h,hbar,nm,k]
,无法从后者中提取“c”
module V (e, c, eV, h, hbar, nm, k, viewAllConstants) where
c = 2.99792458e8
e = exp(1)
eV = 1.602176565e-19
h = 6.62606957e-34
hbar = h/(2*pi)
nm = 1e-9
k = 1.3806488e-23
viewAllConstants = do
putStr (foldl (++) "" (map ("\n" ++)
( zipWith (++) ["c", "e", "eV", "h", "hbar", "nm", "k"]
(map ((" = " ++) . show) [c,e,eV,h,hbar,nm,k])
)
)
)
putsr
、foldl
、map
、zipWith
和show
是GHC随附的模块中定义的函数,它们与您的程序分开编译。这些函数无法知道变量的名称,它们得到的只是它们的值
请注意,与Peter Hall的评论相反,这并不是Haskell与Lisp的区别。在Lisp中,过程的参数通过引用传递给值,而不是符号;Lisp函数不比Haskell函数更了解其参数的名称
此外,您还可以将任意表达式作为参数传递给两种语言中的函数。这些值没有绑定到调用站点中的变量。您可以这样做!你不能像你想的那样做。一些语言实现使用字典来表示表达式的计算环境。一些更愚蠢的人向程序员公开了这种机制。这是愚蠢的,因为它阻止了实现者在将来转向更快的技术。Haskell不会做任何类似的事情,除了可能在类型检查器中。但这并不能阻止你自己建立和使用这样的词典 如果您处理的是一系列相同类型的事情,那么幸运的是,您可以使用
Map
或trie将名称与值连接起来。如果你需要各种各样的东西,你的生活会变得更复杂,例如
尽管如此,我认为你应该仔细考虑你到底有多想要这个。这有点不寻常。在Lisp中可能存在重复,数据和代码之间的区别很模糊,所有内容在运行时都是可检查和动态的。在Haskell中,所有类型和绑定名称在编译时都会被删除,这允许进行大量优化?根据您的具体要求,Template Haskell可能有帮助,也可能没有帮助。@MathematicalArchid我认为现在的问题更好地反映了我想做的事情:打印绑定/标识符的名称,而不是值。该名称在编译时已知@PeterHall:Lisp函数只接收对其参数值的引用。它只知道Haskell函数执行调用方将这些值绑定到的标识符(如果有!)。当然,该名称在编译时已知。。。我想你是想说些别的,但我不太清楚是什么。@ReidBarton哇,这是运行时!编辑。