`MonadWidget` 如何适应 `WidgetFor`?

How does `MonadWidget` fit to `WidgetFor`?

Yesod 有

defaultLayout :: WidgetFor site () -> HandlerFor site Html

setTitle :: MonadWidget m => Html => m ()

WidgetFor site 有一个 MonadWidget 的实例。但是为什么 defaultLayout $ setTitle "..." 可以编译?

setTitle "..." :: MonadWidget m => m () 计算为 any MonadWidget m(例如 MaybeT m 也有一个 MonadWidget 的实例)。

我在这里错过了什么?

setTitle :: MonadWidget m => Html -> m ()

读作调用者和函数实现之间的以下契约

  • 来电者必须选择m
  • 调用者必须确保选择的m满足MonadWidget m约束
  • 调用方必须传递一个 Html 参数
  • 该函数将 return 类型为 m ()
  • 的值

注意不是setTitle选择m。该函数是多态的(或 OOP 术语中的 "generic"),并且可以在调用者选择的任何 m 上工作。

由于 defaultLayout 需要 m = WidgetFor site,GHC 推断在 setTitle 调用中使用了 monad。然后输入所有内容。