gpt4 book ai didi

haskell - 在 Reader monad 中使用 blaze-html 有没有一种不那么尴尬的方法?

转载 作者:行者123 更新时间:2023-12-04 18:08:26 26 4
gpt4 key购买 nike

BlazeHtml tutorial建议使用 Reader monad 用 BlazeHtml 进行现实世界的模板化,但没有说明应该如何做到这一点。我尝试遵循此建议。结果让我很困惑。

为了说明这一点,假设我有一个简单的 User 类型,并且我想使用单独的函数来编写我的 HTML,一个用于布局,另一个用于显示用户信息的 HTML 页面的一部分。如果我使用 Reader Monad,它看起来像这样:

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 monad 的版本进行比较:
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 Monad 如何在实际用例中实际收紧模板代码。我错过了什么吗?

最佳答案

如果你展开你的类型,你会看到

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

关于haskell - 在 Reader monad 中使用 blaze-html 有没有一种不那么尴尬的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20750686/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com