5

BlazeHtml チュートリアルでは、 BlazeHtmlを使用した実際のテンプレート作成に Reader モナドを使用することを提案していますが、これを行う方法については説明していません。この推奨に従ってみました。結果は私を混乱させます。

説明のために、単純な User タイプがあり、別の関数を使用して HTML を作成したいとします。1 つはレイアウト用で、もう 1 つは HTML ページのユーザー情報を表示する部分用です。Reader モナドを使用すると、次のようになります。

data User = User {
    username :: Text
  , userId :: nt
  } deriving (Show)

userBox :: Reader User Html
userBox = do
  user <- ask
  return $ do
      dl $ do
        dt $ "Username"
        dd $ H.toHtml $ username user
        dt $ "UserId"
        dd $ H.toHtml $ userId user

page :: Reader User Html
page = do
  user <- ask
  return $ H.docTypeHtml $ do
    H.head $ title "Reader Monad Blaze Example"
    H.body $ do
      h1 $ "Hello world"
      runReader userBox user

これを Reader モナドを使用しない私のバージョンと比較してください:

userBox :: User -> Html
userBox user = do
      dl $ do
        dt $ "Username"
        dd $ H.toHtml $ username user
        dt $ "UserId"
        dd $ H.toHtml $ userId user

page :: User -> Html
page user = do
  H.docTypeHtml $ do
    H.head $ title "Blaze Example, No Reader Monad"
    H.body $ do
      h1 $ "Hello world"
      userBox user

そのため、実際の使用例で Reader モナドがテンプレート コードを実際にどのように強化できるかを理解するのに苦労しています。何か不足していますか?

4

2 に答える 2

7

タイプを展開すると、

page :: Reader User Html
     :: Reader User Markup
     :: Reader User (MarkupM ())

そのため、トランスフォーマー スタックを使用することで、より多くのレバレッジを得ることができます。

l :: (Html -> Html) -> ReaderT r MarkupM () -> ReaderT r MarkupM ()
l = mapReaderT

r :: Html -> ReaderT r MarkupM ()
r = lift

asksHtml :: ToMarkup a => (r -> a) -> ReaderT r MarkupM ()
asksHtml f = ReaderT (asks (H.toHtml . f))

userBox :: ReaderT User MarkupM ()
userBox = do
      l dl $ do
        r $ dt "Username"
        l dd (asksHtml username)
        r $ dt "UserId"
        l dd (asksHtml userId)

page :: ReaderT User MarkupM ()
page = do
  l H.docTypeHtml $ do
    r $ H.head $ title "Reader Monad Blaze Example"
    l H.body $ do
      r $ h1 "Hello world"
      userBox
于 2013-12-23T20:42:21.137 に答える