我正在玩Snap框架并经常遇到 我根据我得到的参数进行数据库查找的情况 来自表格领域。
考虑例如以下两个功能
getParam :: (MonadSnap m) => ByteString -> m (Maybe ByteString)
doLookup :: (MonadIO (m b v), MonadSnaplet m, MonadState s (m b b), HasAcid s UrlDB) => ByteString -> m b v (EventResult QueryByURL)
其中UrlDB是整数和URL之间的映射。第二种复杂的类型签名
功能是由于使用酸态并最终导致Maybe Integer
。
queryByURL :: Text -> Query UrlDB (Maybe Integer)
到目前为止,我的处理程序看起来像
indexHandler :: Handler MyApp MyApp ()
indexHandler = do
mUrl <- getParam "url"
case mUrl of
Nothing -> render "index"
Just url -> do
mId <- doLookup $ url
case mId of
Nothing -> render "index"
Just i -> do
fancyStuffWith i
render "index"
现在,让我烦恼的第一件事就是案例表达的楼梯。
第二件事是render "index"
的三倍出现。
基本上,每当两个Maybe值中的一个为Nothing时,我想返回
默认视图。
最干净的方法是什么?
答案 0 :(得分:5)
这就是MaybeT monad变换器的用途。你的代码可以这样写。
indexHandler :: Handler MyApp MyApp ()
indexHandler = do
runMaybeT $ do
url <- MaybeT $ getParam "url"
i <- MaybeT $ doLookup url
fancyStuffWith i
render "index"
errors package汇集了这些东西并添加了许多便利功能来处理它们。除了MaybeT之外,EitherT monad变换器也可以执行类似的操作,但会跟踪错误消息,以便您可以跟踪计算失败的时间。
答案 1 :(得分:2)
为了避免重复渲染“index”,你必须看到你基本上在所有代码路径的末尾调用它。然后,您可以尝试使用函数抽象该模式匹配部分。结果并不完美,但略胜一筹。
indexHandler :: Handler MyApp MyApp ()
indexHandler = do
withJust $ getParam "url" $ \url ->
withJust $ doLookup url $ fancyStuffWith
render "index"
where
withJust :: (IO (Maybe a)) -> (a -> IO()) -> IO ()
withJust iomval cmd = do
mval <- iomval
case mval of
Nothing -> return ()
Just val -> cmd val
withJust
函数执行的IO操作可能无法带来值。如果成功,则将值传递给另一个命令。