2012-11-14 41 views
3

我正在嘗試創建一個Haskell程序,它可以畫出一些簡單的2D圖形,但是當您將鼠標懸停在每個圖形上時,它將打印創建形狀的源代碼行。在Haskell中查找函數的行號

爲了做到這一點,我希望能夠創建具有尺寸參數和表示行號的最終參數的形狀。是這樣的:

rect1 = Shape(Rectangle 2 2 lineNumber) 

這將產生寬度爲2個像素,高度2個像素的矩形,並使用一個函數行號來存儲這段代碼被寫就行了。 Haskell中是否存在這樣的函數?創建一個簡單嗎?

我已經搜索堆棧溢出並找到this question回答者建議可以使用C++中的__LINE__編譯指示來達到類似的效果。這是最好的方式去實現它還是有一種方法可以在純Haskell中實現?

+0

'__LINE__'在技術上是不是編譯,這是一個預處理器定義。另外,預處理器實際上與C++沒有關係(它只是C++源代碼文件在編譯前預處理的兼容性),它們可以處理任何文本文件。 –

+0

我認爲在沒有深入研究一些GHC內部構件的情況下,單單在haskell中做這件事將會非常困難。也許使用一些獨立的預處理器。 –

+0

如果你的Haskell實現支持,打開CPP。 – augustss

回答

4

你可以用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" 
1

Pure Haskell不知道源代碼級別的詳細信息。最好的解決方案仍然是用一個外部預處理器預處理一個haskell源文件來嵌入這些信息,這是一個自然分離的問題。

這樣的特性對於動態編程系統來說更有意義,比如Lisp,其中代碼處理和執行階段是及時交錯的。但是AFAIK甚至Common Lisp都沒有這樣的功能,而EmacsLisp(只是因爲它的應用領域是文本編輯器,並不是因爲它的創建者已經這麼做)。

+0

你可以擴展你的東西意味着什麼,或者「用外部預處理器預處理Haskell源文件」的選項?在這個階段,我仍然是Haskell語言的新手。 –

+1

@CraigInnes在Unix領域,有很多文本文件預處理器(m4,imake,GEMA,專用的等等),C預處理器(它繼承到C++)就是其中之一(儘管C詞法結構感知一個),儘管通常對於一些語言很有用。 Haskell的CPP語言擴展只是讓編譯器(例如GHC)在實際編譯之前調用或模擬源文件上的C預處理器(它幾乎總是存在於類Unix系統上)。在Windows操作系統上,它取決於編譯器(例如,GHC分配)來確保所需的預處理器存在。 –

+1

@CraigInnes預處理器只是一個「愚蠢的」工具,它可以使用正則表達式分析文件的詞法結構,並用另一個詞位替換一些詞位,就像它使用'__LINE__'取代一樣,用取自預處理器的內部變量計數輸入線。 –