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 )
这对我来说很好。