【问题标题】:Finding the line number of a function in Haskell在 Haskell 中查找函数的行号
【发布时间】:2012-11-14 13:03:32
【问题描述】:

我正在尝试创建一个 Haskell 程序,该程序在屏幕上绘制一些简单的 2d 形状,但是当您将鼠标悬停在每个形状上时,它会打印创建形状的源代码行。

为了做到这一点,我希望能够创建带有尺寸参数和指示行号的最终参数的形状。像这样的:

rect1 = Shape(Rectangle 2 2 lineNumber)

这将创建一个宽度为 2 像素、高度为 2 像素的矩形,并使用函数 lineNumber 来存储编写这段代码的行。 Haskell中是否存在这样的功能?创建一个简单吗?

我搜索了堆栈溢出并找到this question,其中回答者建议可以使用 C++ 中的 __LINE__ pragma 来实现类似的效果。这是最好的方法还是有办法在纯 Haskell 中做到这一点?

【问题讨论】:

  • __LINE__ 在技术上不是一个编译指示,它是一个预处理器定义。此外,预处理器实际上与 C++ 无关(它只是在编译之前对 C++ 源代码文件进行预处理的 C 遗留兼容性),它们可以处理任何文本文件。
  • 我认为如果不深入研究一些 GHC 内部结构,仅在 haskell 中就很难做到这一点。也许使用一些独立的预处理器。
  • 如果您的 Haskell 实现支持,请开启 CPP。
  • haddock.stackage.org/lts-5.2/base-4.8.2.0/…——现在应该可以使用srcLocStartLine <$> snd <$> take 1 $ getCallStack(通过stackoverflow.com/questions/35261366/…

标签: haskell graphics compiler-construction pragma livecoding


【解决方案1】:

您可以使用 Template Haskell 来做到这一点,它在技术上是另一个 GHC 扩展,但在某种程度上可能比 C 预处理器更“纯”。

here 窃取的代码并稍作修改。

{-# LANGUAGE TemplateHaskell #-}

module WithLocation (withLocation) where
import Language.Haskell.TH

withLocation' :: String -> IO a -> IO a
withLocation' s f = do { putStrLn s ; f }

withLocation :: Q Exp
withLocation = withFileLine [| withLocation' |]

withFileLine :: Q Exp -> Q Exp
withFileLine f = do
    let loc = fileLine =<< location
    appE f loc

fileLine :: Loc -> Q Exp
fileLine loc = do
    let floc = formatLoc loc
    [| $(litE $ stringL floc) |]

formatLoc :: Loc -> String
formatLoc loc = let file = loc_filename loc
                    (line, col) = loc_start loc
                in concat [file, ":", show line, ":", show col]

像这样使用它(来自另一个模块):

{-# LANGUAGE TemplateHaskell #-}

module Main where
import WithLocation

main = do
  $withLocation $ putStrLn "===oo0=Ü=0oo=== Kilroy was here"

【讨论】:

    猜你喜欢
    • 2014-01-05
    • 1970-01-01
    • 2021-03-11
    • 2020-08-23
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多