2013-11-27 2 views
2

Я пытаюсь объединить этот Heist tutorial и этот postgresql-simple tutorial.Используйте результаты postgresql-simple в шаблоне Heist

Я пробовал делать различные варианты этого.

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

Я не знаю, как реализовать эту декларацию экземпляра, и я до сих пор не полностью понимаю монады. Я не уверен, что я даже на правильном пути.

EDIT: Благодаря @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 
+1

О вашем редактировании: три последних функции могут быть ненужными. Просто используйте 'cRender' из модуля' Snap.Snaplet.Heist', чтобы получить обработчик, который вы хотите привязать к маршруту. Конечно, вы должны зарегистрировать сращивание во время фазы инициализации, используя что-то вроде 'addConfig' из' Snap.Snaplet.Heist'. (И если вы используете 'heistServe', вы также можете опустить' cRender', так как имя шаблона выводится из пути.) – danidiaz

+0

Вы правы. Это помогло мне упростить код. Благодарю. – romc

ответ

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 является вашей временной монадой и HeistT n IO является вашей монархией времени загрузки. Если вы работаете в контексте веб-приложения Snap, такого как учебник Janrain, то в вашем случае n будет Handler b b. Вы указали подпись типа Splice IO, которая не будет работать в контексте вашего вопроса, потому что IO не является правильной монадой.

+0

Haskell всегда кажется настолько очевидным после факта. Это то, что мне нужно, чтобы заставить меня на правильном пути. – romc

Смежные вопросы