Невозможно использовать безопасные маршруты типов в виджете дочернего сайта Yesod.

Я работаю над сборкой CMS поверх Yesod для моей выпускной практики. В настоящее время мы используем дочерний сайт (Core) представлять область администратора, это Core должен использоваться повторно между проектами, чтобы он был отделен от главного сайта и имел собственный репозиторий. Должна быть возможность включения других дочерних сайтов для интеграции в Core, Все остальные дочерние сайты должны иметь возможность использовать ту же (администраторскую) компоновку.

Репозитории, которые мы используем:
Ядро CMS: https://github.com/lambdacms/lambdacms-core/tree/extensions
Расширение мультимедиа CMS: https://github.com/lambdacms/lambdacms-media
Демонстрация мастера Yesod: https://github.com/lambdacms/ponycms/tree/media

Обратите внимание, что здесь есть ссылки на конкретные ветки, это те ветки, которые я сейчас использую.

Изначально я использовал функцию lambdaCoreLayout (находится в Foundation.hs), чтобы обеспечить правильную компоновку для всех обработчиков в Core сам. Но я не смог использовать эту функцию на других сайтах. Вместо того, чтобы переписать то, что уже работало, я добавил функцию tryoutLayout (находится в том же файле), который работает для всех дочерних сайтов и очень похож на defaultLayoutSub (который идет с Yesod). Однако это не позволяет мне использовать getRouteToParent в любом из обработчиков, чтобы добавить безопасные маршруты типа к виджетам.

Возьмем следующий фрагмент, например:

getAdminHomeR :: CoreHandler Html
getAdminHomeR = do
  tp <- getRouteToParent
  tryoutLayout [whamlet|@{tp AdminHomeR}|]

Это дает мне следующую ошибку:

Could not deduce (master ~ Core)
from the context (LambdaCmsAdmin master)
  bound by the type signature for
             getAdminHomeR :: LambdaCmsAdmin master =>
                              HandlerT Core (HandlerT master IO) Html
  at LambdaCms/Core/Handler/Home.hs:17:18-33
  ‘master’ is a rigid type variable bound by
           the type signature for
             getAdminHomeR :: LambdaCmsAdmin master =>
                              HandlerT Core (HandlerT master IO) Html
           at <no location info>
Expected type: WidgetT
                 Core
                 IO
                 (yesod-core-1.4.2:Yesod.Routes.Class.Route master
                  -> [(Text, Text)] -> Text)
  Actual type: WidgetT
                 Core
                 IO
                 (yesod-core-1.4.2:Yesod.Routes.Class.Route
                    (HandlerSite (WidgetT Core IO))
                  -> [(Text, Text)] -> Text)
Relevant bindings include
  tp :: yesod-core-1.4.2:Yesod.Routes.Class.Route Core
        -> yesod-core-1.4.2:Yesod.Routes.Class.Route master
    (bound at LambdaCms/Core/Handler/Home.hs:20:3)
  getAdminHomeR :: HandlerT Core (HandlerT master IO) Html
    (bound at LambdaCms/Core/Handler/Home.hs:19:1)
In the first argument of ‘(>>=)’, namely ‘getUrlRenderParams’
In the first argument of ‘tryoutLayout’, namely
  ‘((getUrlRenderParams
     >>=
       (\ urender_agTZ
          -> (asWidgetT . toWidget)
               (toHtml (\ u_agU0 -> urender_agTZ u_agU0 [] (tp AdminHomeR))))))’

Если я прав, эта ошибка говорит о том, что getRouteToParent пытаясь вернуть функцию, которая пытается сгенерировать Route Core вместо Route master, Я пробовал разные места ставить tp <- getRouteToParent но я не смог заставить его работать.

Мои собственные знания Хаскелла и Йесода ограничены, и я не смог найти решение или указатели в правильном направлении. Есть ли что-то, что я пропускаю или есть другой способ, к которому следует подходить?

1 ответ

Решение

Вы хотите, чтобы ваш tryoutLayout функция для получения значения типа WidgetT master IO ()не WidgetT Core IO (), чтобы можно было встраивать маршруты мастер сайтов.

Другие вопросы по тегам