无法在Yesod子网站小部件中使用类型安全路由

时间:2014-11-07 14:30:25

标签: haskell yesod

我正在为Yesod工作,在我的毕业实习期间建立CMS。目前我们使用子网站(Core)来表示管理区域,此Core应该可以在项目之间重复使用,因此它与主站点分离并拥有自己的存储库。应该可以包含其他子网站以集成到Core中。其他子站点都应该能够使用相同的(admin)布局。

我们使用的存储库是:
CMS核心:https://github.com/lambdacms/lambdacms-core/tree/extensions
CMS媒体扩展程序:https://github.com/lambdacms/lambdacms-media
演示Yesod大师:https://github.com/lambdacms/ponycms/tree/media

请注意,urls链接到特定的分支,这些是我目前正在使用的分支。

最初我使用函数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,但我无法让它发挥作用。

我对Haskell和Yesod的了解是有限的,我无法找到正确方向的解决方案或指针。有没有我缺少的东西,还是有另一种方法可以接近它?

1 个答案:

答案 0 :(得分:2)

您希望tryoutLayout函数采用WidgetT master IO ()类型的值,而不是WidgetT Core IO (),以允许您嵌入主站点路由。