Haskell:获取调用者函数名称

dun*_*nno 2 reflection haskell

在 Haskell 中,有没有办法获取调用者函数名称?当然,我可以对其进行硬编码,但这变成了维护负担:如果有人要重命名该函数,则不会强迫他们重命名硬编码名称。

一个人为的例子:

f1 :: String
f1 = "f1" -- can this be automated?
Run Code Online (Sandbox Code Playgroud)

Ben*_*Ben 9

您可以使用 GHC 的CallStack功能来做到这一点。

import GHC.Stack ( HasCallStack, getCallStack, callStack )

foo :: HasCallStack => String -> String
foo s = let ((name, _):_) = getCallStack callStack
         in s <> ": " <> name

main :: HasCallStack => IO ()
main = putStrLn $ foo "This string is being passed to"
Run Code Online (Sandbox Code Playgroud)

产生输出 This string is being passed to: foo

有关完整说明,请参阅我上面的链接,但基本上您可以通过包含HasCallStack约束来要求访问函数中的(部分)调用堆栈。然后callStack得到 a CallStack,它同构于[(String, SrcLoc)],其中每一对的第一个元素是一个函数名;getCallStack将抽象CallStack类型转换为实际的对列表。

(文档似乎声称HasCallStack可以推断出约束,但在我非常简短的实验中并没有发生;如果我callStack在没有签名的函数中使用,我只会得到一个空的调用堆栈;可能最好明确地写一个签名一个HasCallStack约束)