4
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]) 

しかし、それは役に立ちません!

4

1 に答える 1

1

user2407038 は、これを直接行うことは不可能であることを正しく理解しています。最終的に使用した回避策の 1 つは、関数を作成するルーチンから関数に名前を付けるルーチンを抽出することです。次に、同じモジュールで最初のピースを作成した後に呼び出すことができる新しいテンプレート 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 )

これは私にとっては問題ありません。

于 2014-04-16T15:17:33.830 に答える