2017-05-22 27 views
1

有没有什么办法让单个TH功能,定义一个类型,并使用类型?下面的相关代码。 PersonPoly2makeRecordSplice定义,然后传递给makeAdaptorAndInstance(来自Opalaye),这也是TH函数。如何在TemplateHaskell函数中定义一个类型并在同一个函数中使用它?

{-# 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. 

回答

1

您有问题是,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 
{-# 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 
    } 
    |] 

可以明显的makeAdaptorAndInstance "pPerson2" (mkName "PersonPoly2")创建别名,并把它藏在Lib,你就不能有依赖于另外一个在剪接相同的模块。

希望这会有所帮助! :-)

+0

O.P.试图调用monad中的TH函数。这是错误的:TH正在创建必须出现在程序顶层的声明。所以你的回答是正确地把接头放在顶层。 – AntC

相关问题