Finding the line number of a function in Haskell

孤人 提交于 2019-12-04 12:15:49
n. 'pronouns' m.

You can do this with Template Haskell, which is technically yet another GHC extension, but is probably somehow more "pure" than C preprocessor.

Code stolen from here and modified slightly.

{-# 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]

Use it like this (from another module):

{-# LANGUAGE TemplateHaskell #-}

module Main where
import WithLocation

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

Pure Haskell is not aware about source-code-level details. The best solution is still preprocessing a haskell source file with an external preprocessor to embed this information, this is a natural separation of concerns.

Such feature is much more meaningful for dynamic programming systems, like Lisp, where code processing and execution stages are interleaved in time. But AFAIK even Common Lisp does not have such feature, whereas EmacsLisp does (just because its application domain is text editor , not because its creators have decided so).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!