我正在尝试合并此Heist tutorial和此postgresql-simple tutorial。
我尝试过做不同的变化。
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]) }
我不知道如何实现该实例声明,但我仍然没有完全掌握monad。我不确定我是否走在正确的轨道上。
编辑:感谢@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
答案 0 :(得分: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与splice
,Splice n
的类型相同,相当于HeistT n IO Blah
。 Blah
的详细信息对于手头的讨论并不重要。如果您查找manyWithSplices
的类型签名,您会看到它返回Splice n
,所以到目前为止一切看起来都不错。您似乎有runChildren
和projectSplices
正确,所以让我们关注manyWithSplices
的第三个参数。再次参考API文档,我们看到第三个参数的类型为RuntimeSplice n [a]
,因此这是bar
必须具有的类型。但是这个RuntimeSplice
是什么东西。好吧,如果你在API文档中单击它,你会看到它有一个MonadTrans类型类的实例。如果您点击它,您会看到MonadTrans
只定义了一个函数lift
,这在我们这里使用的就足够了。将lift
的类型签名与我们已经找到的内容相结合,可以得出结论:baz
的类型为n [a]
。
n
是您的运行时monad,HeistT n IO
是您的加载时间monad。如果您正在使用像Janrain教程这样的Snap Web应用程序的上下文中,那么在您的情况下n
将是Handler b b
。您指定了类型签名Splice IO
,这在您的问题的上下文中不起作用,因为IO不是正确的monad。