gpt4 book ai didi

haskell - 在模板 haskell 中运行模板 haskell

转载 作者:行者123 更新时间:2023-12-01 05:13:05 33 4
gpt4 key购买 nike

insertST :: StateDecoder -> SomeState -> Update SomeState SomeThing
insertST stDecoder st = ...

StateDecoder 中的东西不能用于
$(makeAcidic ''SomeState ['insertST])

但是如果我声明一个状态并像这样包装它......
myDecoder :: StateDecoder 
myDecoder = ...

insertSomeState :: SomeState -> Update SomeState SomeThing
insertSomeState st = insertST someDecoder

然后它工作

我有很多遵循这种模式的数据类型,所以我想我会写一些 TH 来解决它。
mkWrappedAcid :: Name -> Name -> Q [Dec] 
mkWrappedAcid decoder stname = do
insP@(FunD n _) <- insertMaker decoder stname
acidP <- mkAcidic stname [n]
return $[insP] ++ acidP

insertMaker :: Name -> Name -> Q [Dec]
insertMaker decoder stname = (funD istorename) [(clause [] (normalB insertStTH ) [] )
where
istorename = mkName.concat $ ["insert" , (nameBase stname)]
insertStTH = appE (varE 'insertST ) (varE decoder)

这一切都很好,但是当我尝试运行时......
$(mkWrappedAcid 'myDecoder ''SomeState) 

我得到...
    `insertSomeState' is not in scope at a reify

我知道这与模板 haskell 中的暂存问题有关,但我不知道如何解决。如果我这样做,它会起作用
$(mkWrappedAcid 'myDecoder ''SomeState)
$(makeAcidic ''SomeState ['insertSomeState])

但这无济于事!

最佳答案

好吧,我认为 user2407038 是正确的,不可能直接执行此操作,我最终使用的一种解决方法是从创建它们的例程中提取命名函数的例程。然后你可以构建一个新的模板haskell片段,可以在同一模块中的第一个片段创建后调用......我的方式是这样的。

mkWrappedAcid :: Name -> Name -> Q [Dec] 
mkWrappedAcid decoder stname = do
insP@(FunD n _) <- insertMaker decoder stname
acidP <- mkAcidic stname [n]
return $[insP] ++ acidP

insertMaker :: Name -> Name -> Q [Dec]
insertMaker decoder stname = (funD istorename) [(clause [] (normalB insertStTH ) [] )
where
istorename = mkName.concat $ ["insert" , (nameBase stname)]
insertStTH = appE (varE 'insertST ) (varE decoder)

变成...
mkWrappedAcid :: Name -> Name -> Q [Dec] 
mkWrappedAcid decoder stname = do
(Loc _ _ md _ _) <- location
makeAcidic storename (acidPathMaker md storename)

insertMaker :: Name -> Name -> Q [Dec]
insertMaker decoder stname = (funD istorename) [(clause [] (normalB insertStTH ) [])]
where
insertStTH = appE (varE 'insertST ) (varE decoder)

istorename = mkName.concat $ ["insert" , (nameBase stname)]

acidPathMaker md storename = [modulePlusIname]
where
inameString = nameBase (istorename storename)
modulePlusIname = mkName . concat $ [md , ".", inameString]

通过这种分离,您可以创建包裹的酸状态,例如...
$(acidPathMaker 'myDecoder ''SomeState)
$(mkWrappedAcid ''SomeState )

这对我来说很好。

关于haskell - 在模板 haskell 中运行模板 haskell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23025231/

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