2

このHeist チュートリアルとこのpostgresql-simple チュートリアルを組み合わせようとしています。

私はこれのさまざまなバリエーションを試してみました。

splice :: C.Splice IO  
splice =  do  
  projects <- query_ "SELECT * FROM projects"  
  C.manyWithSplices C.runChildren projectSplice $ return (projects :: [Project])  
  where  
    projectSplice = do  
      "title" ## (C.pureSplice . C.textSplice $ title)  
      "description" ## (C.pureSplice . C.textSplice $ description)  

しかし、私はこのエラーを受け取り続けました。

No instance for (HasPostgres (HeistT IO IO))
  arising from a use of 'query_'
Possible fix:
  add an instance declaration for (HasPostgres (HeistT IO IO))
In a stmt of a 'do' block:
  projects <- query_ "SELECT * FROM projects"
In the expression:
  do { projects <- query_ "SELECT * FROM projects";
       C.manyWithSplices C.runChildren projectSplice 
       $ return (projects :: [Project]) }

そのインスタンス宣言を実装する方法がわからず、モナドをまだ完全に把握していません。正しい軌道に乗っているかどうかさえわかりません。

編集: @mightybyte の回答に感謝し、これを思いつきました。

projectSplice = do
  "title" ## (C.pureSplice . C.textSplice $ title)
  "description" ## (C.pureSplice . C.textSplice $ description)

splice :: C.Splice (Handler App App)
splice =  C.manyWithSplices C.runChildren projectSplice $ lift $ query_ "SELECT * FROM projects"

getHeistState heistConfig = liftIO $ either (error "Heist Init failed") id <$> (runEitherT $ initHeist heistConfig)

getBuilder heistState = maybe (error "Render template failed") fst $ C.renderTemplate heistState "database"

getAllProjectsHeist :: Handler App App ()
getAllProjectsHeist = do
  let heistConfig = HeistConfig defaultInterpretedSplices defaultLoadTimeSplices ("project" ## splice) noSplices [loadTemplates "templates"]
  heistState <- getHeistState heistConfig
  builder <- getBuilder heistState
  writeBS $ toByteString builder
4

1 に答える 1

2

おそらく、次のようなものがもっと必要です。

splice = do
  C.manyWithSplices C.runChildren projectSplices $ 
    lift $ query_ "SELECT * FROM projects"
  where
    projectSplices = do
      "title" ## (C.pureSplice . C.textSplice $ title)
      "description" ## (C.pureSplice . C.textSplice $ description)

ここで重要なのは、型を理解することです。上記の構造に少し注釈を付けましょう。

splice :: Monad n => Splice n
splice = do
  foo
  C.manyWithSplices C.runChildren projectSplices $ do
    bar
    lift baz

シンボル foo は , と同じ型spliceSplice n、 と同等HeistT n IO Blahです。の詳細はBlah、当面の議論にとって重要ではありません。の型シグネチャをmanyWithSplices調べると、それが を返すことがわかるSplice nので、これまでのところすべて問題ないようです。あなたは正しいように見えたrunChildrenのでprojectSplices、 の 3 番目の引数に注目しましょうmanyWithSplices。再び API ドキュメントを参照すると、3 番目の引数には typeRuntimeSplice n [a]が含まれていることがわかりbarます。しかし、これは何RuntimeSpliceですか。API ドキュメントでそれをクリックすると、MonadTrans 型クラスのインスタンスがあることがわかります。MonadTransそれをクリックすると、関数が 1 つだけ定義されていることがわかります。lift、これは私たちがここで使用しているものです。liftの型シグニチャを、すでにわかっているものと組み合わせるとbaz、 が型を持つと結論付けられますn [a]

nは実行時モナドでHeistT n IOあり、ロード時モナドです。JanrainチュートリアルのようなSnap Webアプリケーションのコンテキストで作業している場合、あなたの場合nHandler b b. タイプ signatureSplice IOを指定しましたが、IO は適切なモナドではないため、質問のコンテキストでは機能しません。

于 2013-11-27T15:37:18.367 に答える