Yesod - 直接在模板中包含小部件

时间:2017-04-01 08:56:22

标签: haskell yesod

我有一个脚手架的Yesod应用程序并创建了一个看起来像这样的简单小部件,它位于单独的模块中:

module Widget.Header where

import Prelude
import Yesod

twitterWidget :: MonadWidget m => String -> m ()
twitterWidget twitteruser = do
   toWidgetBody([hamlet| <a href="https://twitter.com/#{twitteruser}" .twitter-follow-button data-show-count="false">Follow @#{twitteruser}
                            <script async src="//platform.twitter.com/widgets.js" charset="utf-8">
                       |])

我已将此模块包含在.cabal文件中,我可以在Handler中加载它并且一切正常。

twitterUsername :: String
twitterUsername = "someusername"

getHomeR :: Handler Html
getHomeR = do
    (formWidget, formEnctype) <- generateFormPost sampleForm
    let submission = Nothing :: Maybe FileForm
        handlerName = "getHomeR" :: Text
    defaultLayout $ do
        let (commentFormId, commentTextareaId, commentListId) = commentIds
        aDomId <- newIdent
        setTitle "Some title"
        twitterWidget twitterUsername 
        $(widgetFile "homepage")

所以我想做的是直接在另一个模板中使用它,但是当我尝试这样做时:

^{twitterWidget twitterUsername}

我得到了

• Ambiguous type variable ‘m1’ arising from a use of ‘toWidget’
      prevents the constraint ‘(ToWidget App (m1 ()))’ from being solved.
      Probable fix: use a type annotation to specify what ‘m1’ should be.
      These potential instances exist:
        instance (site' ~ site, IO ~ m, a ~ ()) =>
                 ToWidget site' (WidgetT site m a)
          -- Defined in ‘Yesod.Core.Widget’
        ...plus one instance involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the second argument of ‘(GHC.Base..)’, namely ‘toWidget’
      In the expression: asWidgetT GHC.Base.. toWidget
      In a stmt of a 'do' block:
        (asWidgetT GHC.Base.. toWidget) (twitterWidget twitterUsername)

所以我的问题是,在网站周围的模板中加载多个小部件以实现不同目的的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

改变你的

module Widget.Header where

import Prelude
import Yesod

twitterWidget :: MonadWidget m => String -> m ()
twitterWidget twitteruser = do
   toWidgetBody([hamlet| <a href="https://twitter.com/#{twitteruser}" .twitter-follow-button data-show-count="false">Follow @#{twitteruser}
                        <script async src="//platform.twitter.com/widgets.js" charset="utf-8">
                   |])

更像是

module Widget.Header where

import Import

twitterWidget :: Yesod site => String -> WidgetT site IO ()
twitterWidget twitteruser = do
   toWidgetBody([hamlet| <a href="https://twitter.com/#{twitteruser}" .twitter-follow-button data-show-count="false">Follow @#{twitteruser}
                        <script async src="//platform.twitter.com/widgets.js" charset="utf-8">
                   |])

那样m肯定会成为IO,而Haskell则无需弄明白。