有什么正确的方法让模板haskell包装一个带有源信息的函数(例如行号) [英] what's the correct way to have template haskell wrap a function with source information (e.g. line number)

查看:107
本文介绍了有什么正确的方法让模板haskell包装一个带有源信息的函数(例如行号)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我从一个函数开始

  fromJust Nothing = errorfrom just nothing nothing! 
fromJust(Just x)= x

然后,我想通过Template添加源信息Haskell更好的错误消息。让我们想象一下,我可以为函数添加一个额外的参数。

  fromJust'loc Nothing = error $from Just'Nothing at+ +(loc_filename loc)
fromJust'loc(Just x)= x

一些 fromJust 我可以在源代码中使用的宏,如$ / $>

  x = $ fromJust $ Map.lookup km 



hack



通过使用quasiquotes并提取源文件名的字符串,我设法破解了它。看来 Loc 没有Lift实例。有没有更好的方法?

  fromJustErr'l(Nothing)= 
error $ printf[internal] fromJust error \
\\\\
(在文件%s中)l
fromJustErr'l(Just x)= x
fromJustErr = do
l < - location
让fn = loc_filename l
fnl :: Q Exp = TH.lift fn
[| fromJustErr'$ fnl |]

谢谢!

< (我知道通过 Maybe 函数可以比 fmap 更好,而不是使用 fromJust ,但我有时需要破解。)

解决方案

这里试图让这个模式更加可重用。
$ b 关键的想法是将一个自定义的错误传递给我们的函数,该函数将包含错误消息中的位置。您可以像这样使用它:

  fromJust'::(String  - > a) - >也许是 - >一个
fromJust'的错误Nothing =错误from just nothing nothing!
fromJust'error(Just x)= x

fromJust :: Q Exp
fromJust = withLocatedError [| from''']

使用此函数与您的原始方法类似:

  main = print(1 + $ fromJust Nothing)


$
$ b

  withLocatedError :: Q Exp  - >现在,对于使这项工作成功的模板Haskell:

  withLocatedError :: Q Exp  - > Q Exp 
withLocatedError f = do
let error = locatedError =<<位置
appE f错误

位置错误:: Loc - > Q Exp
locatedError loc = do
let postfix =at++ formatLoc loc
[| \msg - >错误(msg ++ $(litE $ stringL postfix))|]

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

locatedError 产生定制的错误函数,给定一个位置。 withLocatedError 将此内容反馈给 fromJust'以将所有内容挂钩在一起。 formatLoc 只是很好地将位置格式化为一个字符串。



运行这个程序给了我们想要的结果:

  FromJustTest:fromJust nothing nothing!在FromJustTest.hs:5:19 


Suppose I start with a function

fromJust Nothing = error "fromJust got Nothing!"
fromJust (Just x) = x

Then, I want to add source information via Template Haskell for better error messages. Let's imagine that I could add an extra parameter to the function

fromJust' loc Nothing = error $ "fromJust got Nothing at " ++ (loc_filename loc)
fromJust' loc (Just x) = x

and then have some fromJust macro that I could use in source code like,

x = $fromJust $ Map.lookup k m

hack

I did manage to hack it, by using quasiquotes and lifting the string of the source filename. It seems that Loc doesn't have a Lift instance. Is there a better way?

fromJustErr' l (Nothing) =
    error $ printf "[internal] fromJust error\
        \\n    (in file %s)" l
fromJustErr' l (Just x) = x
fromJustErr = do
    l <- location
    let fn = loc_filename l
        fnl :: Q Exp = TH.lift fn
    [| fromJustErr' $fnl |]

Thanks!

(I know it's nicer to fmap stuff via the Maybe functor than use fromJust, but I need to hack sometimes.)

解决方案

Here's an attempt at making this pattern somewhat more reusable.

The key idea is to pass a customized error to our function which will include the location in the error message. You'd use it like this:

fromJust' :: (String -> a) -> Maybe a -> a
fromJust' error Nothing = error "fromJust got Nothing!"
fromJust' error (Just x) = x

fromJust :: Q Exp
fromJust = withLocatedError [| fromJust' |]

Using this function is similar to your original approach:

main = print (1 + $fromJust Nothing)

Now, for the Template Haskell that makes this work:

withLocatedError :: Q Exp -> Q Exp
withLocatedError f = do
    let error = locatedError =<< location
    appE f error

locatedError :: Loc -> Q Exp
locatedError loc = do
    let postfix = " at " ++ formatLoc loc
    [| \msg -> error (msg ++ $(litE $ stringL postfix)) |]

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

locatedError produces the customized error function, given a location. withLocatedError feeds this to fromJust' to hook everything together. formatLoc just formats the location nicely into a string.

Running this gives us the result we wanted:

FromJustTest: fromJust got Nothing! at FromJustTest.hs:5:19

这篇关于有什么正确的方法让模板haskell包装一个带有源信息的函数(例如行号)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆