haskellroutesyesodhamlet

Route Interpolation fails with type error in Yesod Handler


I have a simple Yesod handler that renders a single Html tag like so:

getHomeR :: Yesod site => HandlerT site IO Html
getHomeR = defaultLayout
  [whamlet|$newline never
<h1>Hello!
|]

I would like to print the route, and change the code to use the @{HomeR} route interpolation syntax, like this:

getHomeR :: Yesod site => HandlerT site IO Html
getHomeR = defaultLayout
  [whamlet|$newline never
<h1>@{HomeR}
|]

Interpolating routes in my Yesod handler fails with this error:

• Couldn't match type ‘site’ with ‘App’
  ‘site’ is a rigid type variable bound by
    the type signature for:
      getHomeR :: forall site. Yesod site => HandlerT site IO Html
    at Handler/Home.hs:12:13
  Expected type: WidgetT
                   site IO (Route App -> [(Text, Text)] -> Text)
    Actual type: WidgetT
                   site
                   IO
                   (Route (HandlerSite (WidgetT site IO)) -> [(Text, Text)] -> Text)

Solution

  • Your type Yesod site => HandlerT site IO Html allows for site to be any Yesod instance however, the handler function will only work in the site it is created for.

    In this case your Yesod instance is called App (I believe this is the default for the scaffolding site). Therefore the correct type would be: HandlerT App IO Html

    Presuming you're using the scaffolding site (due to your answer mentioning Handler) then Yesod creates the type synonym Handler to mean HandlerT App IO so you don't have to keep typing it out.

    This is why, as you discovered, Handler Html works and your original version doesn't.