如何在TemplateHaskell函数中定义类型并在同一函数中使用它?

如何在TemplateHaskell函数中定义类型并在同一函数中使用它?,haskell,template-haskell,Haskell,Template Haskell,有没有办法将其作为单个TH函数,定义一个类型,并使用该类型?相关代码如下PersonPoly2由makeRecordSplice定义,然后传递给MakeAdapterAndInstance(来自Opalaye),这也是一个函数 {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE Mul

有没有办法将其作为单个TH函数,定义一个类型,并使用该类型?相关代码如下
PersonPoly2
makeRecordSplice
定义,然后传递给
MakeAdapterAndInstance
(来自Opalaye),这也是一个函数

{-# LANGUAGE FlexibleContexts       #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE OverloadedStrings      #-}
{-# LANGUAGE TemplateHaskell        #-}

module Lib where

import           Data.Profunctor.Product.TH             (makeAdaptorAndInstance)
import Language.Haskell.TH

makeRecordSplice :: Q [Dec]
makeRecordSplice = [d|
  data PersonPoly2 a b = Person2
    { id :: a 
    , name :: b
    }
  |]

makeRecordAndAdapter :: Q [Dec]
makeRecordAndAdapter = do
  record <- makeRecordSplice
  adapter <- makeAdaptorAndInstance "pPerson2" (mkName "PersonPoly2")
  return $ record ++ adapter


-------------

/home/Projects/scratch/app/Main.hs:26:1: error:
    ‘PersonPoly2’ is not in scope at a reify
Failed, modules loaded: Lib.
{-#语言灵活上下文}
{-#语言灵活实例}
{-#语言功能依赖性}
{-#语言MultiParamTypeClasses}
{-#语言重载字符串}
{-#语言模板haskell}
模块库在哪里
导入Data.Profunctor.Product.TH(MakeAdapterAndInstance)
导入语言.Haskell.TH
makeRecordSplice::Q[Dec]
makeRecordSplice=[d|
数据人员2 a b=人员2
{id::a
,姓名::b
}
|]
makeRecordAndAdapter::Q[Dec]
makeRecordAndAdapter=do

record您遇到的问题是,
makeRecordSplice
需要位于与其实例化的模块不同的模块中。该模板的Haskell限制确保了编译时的非循环依赖关系。这是一个恼人的限制,但不太难做到。以下是一种方法:

{-# LANGUAGE FlexibleContexts       #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE OverloadedStrings      #-}
{-# LANGUAGE TemplateHaskell        #-}

module Main where

import           Data.Profunctor.Product.TH (makeAdaptorAndInstance)
import           Language.Haskell.TH
import           Lib                        (makeRecordSplice)


$(makeRecordSplice)
$(makeAdaptorAndInstance "pPerson2" (mkName "PersonPoly2"))

main :: IO ()
main = undefined
显然,您可以为
MakeAdapterAndInstance“pPerson2”(mkName“PersonPoly2”)
创建别名并将其隐藏在
Lib
中,您只是不能让一个拼接依赖于同一模块中的另一个拼接


希望这有帮助!:-)

O.p.试图调用monad中的TH函数。这是错误的:TH创建的声明必须出现在程序的顶层。因此,您的答案是正确地将拼接放在顶层。
{-# LANGUAGE FlexibleContexts       #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE OverloadedStrings      #-}
{-# LANGUAGE TemplateHaskell        #-}

module Lib where

import           Data.Profunctor.Product.TH (makeAdaptorAndInstance)
import           Language.Haskell.TH

makeRecordSplice :: Q [Dec]
makeRecordSplice = [d|
  data PersonPoly2 a b = Person2
    { id :: a
    , name :: b
    }
  |]