路由插值因 Yesod 处理程序中的类型错误而失败

Route Interpolation fails with type error in Yesod Handler

我有一个简单的 Yesod 处理程序,它呈现单个 Html 标记,如下所示:

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

我想打印路线,并更改代码以使用 @{HomeR} 路线插值语法,如下所示:

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

在我的 Yesod 处理程序中插入路由失败并出现此错误:

• 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)

将类型签名更改为 getHomeR :: Handler Html

您的类型 Yesod site => HandlerT site IO Html 允许站点是任何 Yesod 实例,但是,处理程序函数将仅在为其创建的站点中工作。

在这种情况下,您的 Yesod 实例称为 App(我相信这是脚手架站点的默认设置)。因此正确的类型是: HandlerT App IO Html

假设您使用的是脚手架网站(由于您的回答提到 Handler),那么 Yesod 会创建类型同义词 Handler 来表示 HandlerT App IO,因此您不必继续打字。

这就是为什么,如您所见,Handler Html 有效而您的原始版本无效。