Search code examples
haskellyesod

How do I pass additional variables to defaultLayout in a Yesod handler?


I want to do something similar to what I'm trying below. Seems like I need to learn more about Monads. Any pointers? I did use yesod init to get going and yesod add-handler to create the handler.

In Handler/Hello.hs:

getHelloR :: Handler Html
getHelloR = do
    let hello = "Hello World"
    defaultLayout $ do
        $(widgetFile "hello")

In templates/hello.hamlet:

<h1>Test
<p>#{hello}

The error I'm getting when running cabal-dev install && yesod --dev devel is:

Handler/Hello.hs:9:11:
    Ambiguous type variable `a0' in the constraints:
      (Data.String.IsString a0)
        arising from a use of `hello' at Handler/Hello.hs:9:11-28
      (blaze-markup-0.5.1.5:Text.Blaze.ToMarkup a0)
        arising from a use of `toHtml' at Handler/Hello.hs:9:11-28
    Probable fix: add a type signature that fixes these type variable(s)
    In the first argument of `toHtml', namely `hello'
    In the first argument of `asWidgetT . toWidget', namely
      `toHtml hello'
    In a stmt of a 'do' block: (asWidgetT . toWidget) (toHtml hello)

Solution

  • What this error message means is "I know that the hello variable is some kind of IsString instance, but I don't know which one." In other words, hello would be of type String, Text, Html, or something else, but the compiler can't figure it out based on the information you're providing. The easiest was to solve this is to add an explicit type signature, e.g.:

    let hello :: String
        hello = "Hello World"
    

    This is a somewhat common issue that arises when using OverloadedStrings.