如何避免模板 Haskell 声明引用中的额外缩进?

dav*_*420 5 haskell template-haskell

我有一个玩具程序:

$ cat a.hs
main = putStrLn "Toy example"
$ runghc a.hs
Toy example
Run Code Online (Sandbox Code Playgroud)

让我们向其中添加一些模板 Haskell:

$ cat b.hs
{-# LANGUAGE TemplateHaskell #-}
id [d|
main = putStrLn "Toy example"
|]
$ runghc b.hs

b.hs:3:0: parse error (possibly incorrect indentation)
Run Code Online (Sandbox Code Playgroud)

那么,让我们修复缩进:

$ cat c.hs
{-# LANGUAGE TemplateHaskell #-}
id [d|
 main = putStrLn "Toy example"
 |]
$ runghc c.hs
Toy example
Run Code Online (Sandbox Code Playgroud)

一个空格就足够了,但我必须缩进两个尾随行。

我可以避免缩进我的大部分模块吗?(我的 Real Modules 不止一行代码。)(而且没有使用{ ; ; }符号?)

我确实希望在引用中捕获所有模块声明 - 在正常代码中我可以替换(...)$ ...,是否有一些等效的[d|...|]可以让我避免使用右括号和缩进?

或者是有一些方法模块一个可以说,任何模块的顶层声明一个被导入由函数自动处理一个出口?

笔记:

  1. 我的真实程序中的模板 Haskell 比id它更复杂——它扫描变量名的声明prop_,并构建一个包含它们的测试套件。是否有其他一些纯粹的 Haskell 方法可以代替我执行此操作,而无需直接修改源文件?
  2. 我正在使用 GHC v6.12.1。当我使用 GHC v7.0.3 时,针对不同位置报告了 b.hs 的错误b.hs:3:1——但行为在其他方面是相同的。

ham*_*mar 3

[我的程序] 扫描以 prop_ 开头的变量名称的声明,并构建包含它们的测试套件。有没有其他一些纯粹的 Haskell 方法可以代替,而不直接修改源文件?

就在这里!使用language-haskell-extract

{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.Extract
import Test.QuickCheck

prop_foo xs = reverse (reverse xs) == (xs :: [Int])
prop_bar = 2 + 2 == 4

properties = $(functionExtractorMap "^prop_"
    [|\name prop -> putStrLn name >> quickCheck prop|])

main = sequence_ properties
Run Code Online (Sandbox Code Playgroud)

运行这个,我们得到:

prop_foo
+++ OK, passed 100 tests.
prop_bar
+++ OK, passed 100 tests.
Run Code Online (Sandbox Code Playgroud)

然而,在你重新发明轮子之前,我还建议你看一下这个test-framework-th,它几乎完全做到了这一点,而且还支持 HUnit 并有一个很好的测试运行器(带有颜色!)。

{-# LANGUAGE TemplateHaskell #-}

import Test.Framework.Providers.HUnit
import Test.Framework.Providers.QuickCheck2
import Test.Framework.TH
import Test.HUnit
import Test.QuickCheck

prop_bar = 1+1 == 2
case_foo = 2+2 @?= 4

main = $(defaultMainGenerator)
Run Code Online (Sandbox Code Playgroud)

输出:

Main:
  bar: [OK, passed 100 tests]
  foo: [OK]

         Properties  Test Cases  Total      
 Passed  1           1           2          
 Failed  0           0           0          
 Total   1           1           2   
Run Code Online (Sandbox Code Playgroud)

testGroupGenerator如果您想组合多个文件中的测试,还有一个很有用。