gpt4 book ai didi

haskell - 减少 happstack 教程代码中的冗余

转载 作者:行者123 更新时间:2023-12-01 09:06:14 26 4
gpt4 key购买 nike

happstack 教程提供了以下示例:

main :: IO ()
main = simpleHTTP nullConf $ msum
[ do methodM GET
ok $ "You did a GET request.\n"
, do methodM POST
ok $ "You did a POST request.\n"
, dir "foo" $ do methodM GET
ok $ "You did a GET request on /foo.\n"
]

似乎 ok $ 在这里是多余的 - 有没有办法将它从 msum 中提取出来,这样你就不必编写 ok $ 三倍?我尝试了以下方法,但它甚至没有编译:

main :: IO ()
main = simpleHTTP nullConf $ ok $ msum
[ do methodM GET
"You did a GET request.\n"
, do methodM POST
"You did a POST request.\n"
, dir "foo" $ do methodM GET
"You did a GET request on /foo.\n"
]

有没有正确的方法来做到这一点(或者甚至更好,提取整个 ok $ "You did a " and ".\n"),还是不可能?

我仍在快速了解 monad 在 Haskell 中的工作方式,但如果上述情况不可行,那么您能否从高层次上解释为什么没有合理的方法可以使这项工作发挥作用,或者需要做什么为了让它成为可能而改变?我只是想弄清楚这里可以做什么和不能做什么。

最佳答案

ok 并不是真的多余。

让我们近距离看看其中一个 do block 。我们将第一个 do-block 拆分成一个名为 getPart 的单独函数。

getPart :: ServerPart String
getPart = do methodM GET
ok $ "You did a GET request.\n"

所以,我们清楚地看到我们正在使用 ServerPart monad。因此,do block 中的每一行都必须具有像 ServerPart a 这样的类型。

这样写行不通:

getPart :: ServerPart String
getPart = do methodM GET
"You did a GET request.\n"

因为该 do block 中的最后一行具有 String 类型,而不是需要 ServerPart String。将 String 转换为 ServerPart String 的典型方法是使用 return:

getPart :: ServerPart String
getPart = do methodM GET
return "You did a GET request.\n"

记住 return 的类型是:

return :: (Monad m) => a -> m a

但是,当然,这并不比我们以前的更好。我们用 return 代替 ok。真的没有办法避免那个'样板'。您需要一个 ServerPart String 而不是 String 这意味着应用像 returnok 这样的函数来完成提升.

正如您所注意到的,消息的 "You did a " 部分是多余的。我们有几种方法可以解决这个问题。我们可以让处理程序只返回消息中不同的部分,如下所示:

handlers :: ServerPart String
handlers =
[ do methodM GET
ok $ "GET request"
, do methodM POST
ok $ "POST request"
, dir "foo" $ do methodM GET
ok $ "GET request on /foo"
]

然后我们可以得到那个 String 并添加消息的其余部分:

main :: IO ()
main = simpleHTTP nullConf $ do msg <- handlers
return ("You did a " ++ msg ++ ".\n")

(这可以更简洁地表达,但我在这里的目标是可读性)。

该解决方案的一个问题是它强制所有这些处理程序符合完全相同的模具。如果我们想添加一个返回不符合该模式的消息的处理程序,我们就会遇到麻烦。另一种选择是创建一个简单的辅助函数来封装该模式:

methodMsg :: Method -> String -> ServerPart String
methodMsg mthd msg = do methodM mthd
ok $ "You did a " ++ msg ++ ".\n"

main :: IO ()
main = simpleHTTP nullConf $ msum
[ methodMsg GET "GET request"
, methodMsg POST "POST request"
, dir "foo" $ methodMsg GET "GET request on /foo"
-- the bar handler does not follow the pattern
, dir "bar" $ ok $ "let's go to the bar!"
]

希望这会有所帮助!

关于haskell - 减少 happstack 教程代码中的冗余,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7153067/

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