使用 Derive 导出 Uniplate

Deriving Uniplate with Derive

我的程序正在大量使用 Uniplate.Data,希望提高其性能。

目前我正在使用 DeriveDataTypeable GHC 扩展自动派生 Data 个实例。

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Data
import Data.Generics.Uniplate.Data

data Expr = Val Int
          | Neg Expr
          | Add Expr Expr
  deriving (Data,Typeable)

Uniplate.Data package description recommend using Uniplate.Direct 因为性能优越。 后者需要为数据类型编写显式 Uniplate 实例,并为此推荐 Derive 工具。

尝试使用 Derive 自动派生实例时:

{-# LANGUAGE TemplateHaskell #-}
import Data.DeriveTH
import Data.Generics.Uniplate.Direct

data Expr = Val Int
          | Neg Expr
          | Add Expr Expr

$( derive makeUniplateDirect ''Expr )

我收到以下错误:

Exception when trying to run compile-time code:
  Derivation of UniplateDirect does not yet support Template Haskell, requires info for Expr
Code: derive makeUniplateDirect ''Expr

是否有任何其他方法可以自动派生 Uniplate.Direct 个实例?

谢谢!

正如错误信息所说,UniplateDirect不支持derive的TH模式,因此您必须使用独立可执行版本作为预处理器来生成Uniplate实例.

您可以通过添加 {-! !-} 指令并通过 GHC 将 derive 设置为 运行 的预处理器来实现:

{-# OPTIONS_GHC -F -pgmFderive -optF-F #-}
import Data.Generics.Uniplate.Direct

data Expr = Val Int
          | Neg Expr
          | Add Expr Expr

{-!
deriving instance UniplateDirect Expr
!-}

将此加载到 GHCi 中进行快速测试可确认您拥有自己的实例:

[1 of 1] Compiling Main             ( SO31725183.hs, interpreted )
Ok, modules loaded: Main.
*Main> :i Expr
data Expr = Val Int | Neg Expr | Add Expr Expr
        -- Defined at D:\cygwin\tmp\ghc13224_0\ghc13224_3.hspp:6:1
instance Uniplate Expr
  -- Defined at D:\cygwin\tmp\ghc13224_0\ghc13224_3.hspp:16:10