gpt4 book ai didi

haskell - 获取里面的函数名

转载 作者:行者123 更新时间:2023-12-04 10:28:00 25 4
gpt4 key购买 nike

我有一堆函数,例如:method1 , method2 , method3 .对于所有这些,有HUnit测试函数如:testMethod1 , testMethod2 , testMethod3 .

testMethod1 = TestCase $
assertEqual "testmethod1" ...

testMethod2 = TestCase $
assertEqual "testmethod2" ...

testMethod3 = TestCase $
assertEqual "testmethod3" ...

我想避免函数名称的冗余复制作为错误的前缀
消息并将其称为:
testMethod1 = TestCase $
assertEqual_ ...

如何实现(赞赏任何“魔术”技巧)?

所以实际上的问题是如何在它的定义中使用函数名称?

更新 .

从原始问题中实际上并不清楚,我也想处理这种情况:
tProcess = TestCase $ do
assertEqual "tProcess" testResult $ someTest
assertEqual "tProcess" anotherTestResult $ anotherTest
assertEqual "tProcess" resultAgain $ testAgain

最后我想写这样的东西:
tProcess = TestCase $ do
assertEqual_ testResult $ someTest
assertEqual_ anotherTestResult $ anotherTest
assertEqual_ resultAgain $ testAgain

最佳答案

您不能直接执行此操作(即,您的测试用例以 testMethodN = ... 开头),但您可以使用 Template Haskell得到这个:

testCase "testMethod1" [| do
assertEqual_ a b
assertEqual_ c d
|]

这涉及到写 testCase :: String -> Q Exp -> Q [Dec] ,一个将测试用例的名称和引用的表达式转换为声明列表的函数。例如:
{-# LANGUAGE TemplateHaskell #-}
    
import Data.Char
import Control.Applicative
import Control.Monad
import Language.Haskell.TH
import Data.Generics

assertEqual :: (Eq a) => String -> a -> a -> IO ()
assertEqual s a b = when (a /= b) . putStrLn $ "Test " ++ s ++ " failed!"

assertEqual_ :: (Eq a) => a -> a -> IO ()
assertEqual_ = error "assertEqual_ used outside of testCase"

testCase :: String -> Q Exp -> Q [Dec]
testCase name expr = do
    let lowerName = map toLower name
    e' <- [| assertEqual lowerName |]
    pure <$> valD
        (varP (mkName name))
        (normalB (everywhere (mkT (replaceAssertEqual_ e')) <$> expr))
        []
  where
replaceAssertEqual_ e' (VarE n) | n == 'assertEqual_ = e'
replaceAssertEqual_ _ e = e

这里的基本思想是生成给定名称的定义,并替换变量 assertEqual_ 的每次出现。在带有 assertEqual lowerName 的引用表达式中.感谢 Template Haskell 的 Scrap Your Boilerplate支持,我们不需要遍历整个AST,只需为每个 Exp指定一个变换即可节点。

请注意 assertEqual_必须是具有正确类型的绑定(bind)标识符,因为引用的表达式在传递给 testCase 之前会进行类型检查.此外, testCase由于 GHC 的阶段限制,必须在与其使用的模块不同的模块中定义。

关于haskell - 获取里面的函数名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10036567/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com