【问题标题】:Haskell Yesod get user credentials in subsiteHaskell Yesod 在子站点中获取用户凭据
【发布时间】:2018-01-23 12:10:28
【问题描述】:

我正在为我的 yesod 项目编写一个子站点,我需要在该子站点上显示登录用户的名称(我正在使用 yesod-auth 硬编码,其中 AuthId master = Text 的类型)。

但是,用户在主站点上登录。我可以使用maybeAuthId 获得AuthId master 类型的值,但我无法显示该值,因为它不是Show 的实例。

我可以对我的处理程序施加类型约束以确保AuthId master 的类型派生Show?

getSubsiteHomeR :: (YesodAuth master) => HandlerT Subsite (HandlerT master IO) Html
getSubsiteHomeR = do
   lift $ do
     maid <- maybeAuthId -- I want to display the value of 'maid'
     liftIO $ print maid
     defaultLayout [whamlet|.......|]

编辑:这是错误消息:

Could not deduce (Show (AuthId master))
    arising from a use of `print'
  from the context: YesodAuth master
    bound by the type signature for:
               getSubsiteHomeR :: YesodAuth master =>
                                     HandlerT Subsite (HandlerT master IO) Html
    at src/Subsite.hs:24:1-89
* In the second argument of `($)', namely `print maid'
  In a stmt of a 'do' block: liftIO $ print maid
  In the second argument of `($)', namely
    `do { maid <- maybeAuthId;
          liftIO $ print maid;
          defaultLayout
            (do { (asWidgetT . toWidget)
                    ((blaze-markup-0.8.0.0:Text.Blaze.Internal.preEscapedText . T.pack)
                       "<p>Welcome to the Subsite!</br><a href=\"");
                  (getUrlRenderParams
                   >>=
                     (\ urender_alJ6
                        -> (asWidgetT . toWidget)
                             (toHtml
                                ((\ u_alJ7 -> urender_alJ6 u_alJ7 ...)
                                   (toParent SubsiteHomeR)))));
                  (asWidgetT . toWidget)
                    ((blaze-markup-0.8.0.0:Text.Blaze.Internal.preEscapedText . T.pack)
                       "\">Subsite</br></a>\n\
                       \<a href=\"");
                  .... }) }'

【问题讨论】:

    标签: haskell yesod


    【解决方案1】:

    在我看来,您需要的只是类型签名中的 Show (AuthId master) 约束:

    getSubsiteHomeR :: (YesodAuth master, Show (AuthId master)) => HandlerT Subsite (HandlerT master IO) Html
    

    请注意,这需要 FlexibleContexts 语言扩展名,您可以通过将 {-# LANGUAGE FlexibleContexts #-} 放在源文件顶部来启用它。

    【讨论】:

    • 我认为是FlexibleContexts。无论如何,Yesod基本上都需要{-# LANGUAGE AllTheExtensions #-},所以作者应该没问题。
    • 当我尝试更改时出现错误* Non type-variable argument in the constraint: Show (AuthId master) (Use FlexibleContexts to permit this) * In the type signature: getFileserverHomeR :: (YesodAuth master, Show (AuthId master)) =&gt; HandlerT Fileserver (HandlerT master IO) Html
    • @frankhucek 是的,您需要在源文件顶部使用{-# LANGUAGE FlexibleContexts #-} 才能使其工作。我会把它添加到答案中。
    • @Cubic 添加{-# LANGUAGE FlexibleContexts #-} 解决了这个问题。谢谢!为什么这是必要的?
    • @frankhucek 函数约束的原始定义只允许 Constraint typeVariable 形式的约束。我们这里的约束比这更复杂:Constraint (SomeTypeFunction typeVariable)。正如您所见,这很有用,但还不是基础语言的一部分,这就是为什么它依赖于语言扩展。我在答案中链接了一个解释页面,其中包含更多详细信息。
    猜你喜欢
    • 2015-08-02
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2014-04-19
    • 1970-01-01
    • 2015-06-30
    • 2014-12-05
    • 2016-11-02
    相关资源
    最近更新 更多